1

I have multiple classes in my current project like HTMLRequest, SPDYRequest, BHIVERequest. I get data from a network stream and I want to find out, which of the classes can handle this data. For this I read the header of the Stream packet (All protocols are in the same form, so I can read until I get empty line (\r\n) ) and then pass this header to a static function in the request classes which returns a boolean which tells whether it is a header for this kind of request or not. Now I want to be able to load specific Protocols at runtime (from plug-ins). What is the best way to be able to check whether I have a Protocol for a header or not.

My thoughts were:

  • An extra class Protocol as a singleton, which then is registered in a RequestFactory, that then has to find out which Protocol can create a request for this kind of header and calls Protocol.assemble()

  • A static List of Class<? extends Request> so I can call the static methods through reflection or by Class.newInstance()

I don't like both that ideas, so what is the right way to dynamically do this stuff in Java?

th3falc0n
  • 1,389
  • 1
  • 12
  • 33
  • If you serch way to load classes at runtime from plugins, may be you serch somthing like [OSGI](http://www.osgi.org/Main/HomePage). For example eclipse works at this technology([equinox](http://www.eclipse.org/equinox/)) ? – alex2410 Nov 01 '13 at 16:24
  • The loading itself is not really my problem. My problem is how to check which of the classes is suitable for my input data from the network stream. – th3falc0n Nov 01 '13 at 16:26

1 Answers1

2

If it were me, I'd do something similar, but not identical, to option 1:

  • Read all plugins at startup, storing their headers and a reference to either their class name or an instance (if they're stateless) in a HashMap in a RequestFactory or similarly named utility. You'd also store references to the built-in system protocols in this map.
  • When a request comes in, make a call to RequestFactory.getProtocol(String header) to grab a reference to the protocol that should be used.

Note that if you go this route, you don't need a method in each protocol class that lets you query whether a header is appropriate for it; the factory handles that for you.

Edit

...I just noticed the "at runtime" part of your question, which makes the "at startup" part of my solution a little out of place. New plugins could still be registered into the factory's internal map as they're recognized/loaded; that shouldn't affect the usefulness of this design as a whole.

Josh
  • 1,563
  • 11
  • 16
  • I already thought that this would be the only way to do this in Java, but how would you excatly implement the HashMap? It is not as simple because you maybe don't even have a string in the first line but a binary protocol which then just ends the header with \r\n\r\n in binary form, so need to call the Protocol.isSuitableFor(header) method to decide whether the protocol can handle the data or not. – th3falc0n Nov 01 '13 at 16:20
  • Whether you have a `byte[]` or `String` in any given header, the headers are still unique, right? I'd key the `HashMap` on whichever format is more common, then overload the `getProtocol` method to accept both formats as input. If you choose to key on `String`, the implementation for the version that accepts a `byte[]` could be as simple as calling `getProtocol(new String(byteArr, "UTF-8"))` (substitute your encoding of choice, of course). – Josh Nov 01 '13 at 16:29
  • That is the other part of the Problem. They aren't unique at all. "GET / HTTP/1.1" is HTTP, "POST /users/1234 HTTP/1.0" is also HTTP. – th3falc0n Nov 01 '13 at 16:33
  • Ah, gotcha. In that case, I'd extend the design a bit to include a `HeaderParser` (or something similar) utility designed to pull the protocol name from the header and feed that to the factory. I'm not sure of the range of protocols you're trying to support here, so maybe that's not feasible, and you'll just have to loop over all currently loaded protocols, but this would be the first thing I'd try. – Josh Nov 01 '13 at 16:42
  • Since the whole thing is a RESTful web-service I think you pushed me in the right direction. I will implement a List of Protocols in the RequestFactory and will implement an universal Request class, which has an assigned protocol. This way I should be able to reduce the overhead for needing 2 classes for each protocol while achieving what I want to achieve. Thanks for your help and ideas. – th3falc0n Nov 01 '13 at 16:50