• Post Reply Bookmark Topic Watch Topic
  • New Topic

Processing a queue containing dissimilar messages  RSS feed

 
Sreeni Nair
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am new to Java/OOP in general, and am trying to implement a multi-threaded system that contains a master thread, and a set of worker threads that are heterogeneous in the work they do. Once they complete the work, the workers indicate to the master by posting the result on to its queue. Here is the problem. The results of each type of work is different, and the master has to process each differently. In C (which I'm familiar with), this can be achieved by having a message type that is a union of all the expected messages, and by using a switch statement. I thought of doing something similar in Java, by using instanceof on each incoming message (each individual message class having been subclassed from a super message class) , and doing switch on that, but it doesn't seem to be the OO way to do things. The only other way I could think of was to implement an abstract method to get the type of each message, and then use the type in a switch statement, or if-then-else. Is there some other Java idiom to do this kind of processing? Also, if this is an acceptable method, why is it superior to using the refelection to find out the message type (instead of using the abstract getType())? Thank you in advance for any thoughts.

PS:

The message types look similar to the code below:
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, welcome to the Rach.

Using a switch statement is definitely not the OO way to do this. The OO method would be for the messages to know how to process themselves. I'm not sure what sort of processing you're going to want to do, but it would look something like follows:



In the above code the type of processing that will be performed will be determined by the specific type of the Message. Your code will adhere to the SOLID Open Closed Principle because you don't need to change existing code to add new Message types, you just write a new class that implements Message and provides the process() functionality.

An alternative approach would be to use the Visitor Pattern. This might look something like the following:



In this code the MessageProcessor is responsible for doing the processing. In order to know what type of processing to do it overloads the method process() for each of the different Message types, and so can handle each one differently. The Message implementations each accept a MessageProcessor, and call the appropriate overload of the process() method on it. The Message implementations know what type they are so can do that. This is similar to having a getType() method on Message and then using a switch statement. This does not pass the Open/Closed principle I mentioned above as now you need to add functionality to the MessageProcessor for each new Message type. It may be useful if you know you will never add new Message types in the future, and you need to amalgamate the results of the processing in a single place.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sam Null wrote:In C (which I'm familiar with), this can be achieved by having a message type that is a union of all the expected messages, and by using a switch statement.

Which is a perfectly reasonable method. The only problem with it (as I suspect you already know) is that it's procedural - ie, it relies on every "actor" operating in accordance with that procedure. If they don't, they get nothing (or garbage).

So, you try to determine this by type (which is certainly one way to do it), but you're now constrained by another factor: types in Java are hierarchical (single inheritance, remember ). So, if your messages can't be "selected" according to hierarchy, it's not going to work.
But at least you're thinking about it objectively, which is very important; so well done for that.

One possibility would be to create an Enum of all the types of messages you're likely to want to filter on, and have each message contain an EnumSet of the values that should return "true". This is basically a slightly more "Java-compliant" model of your procedural "union", and I suspect might well do what you want.
Another (possibly even better, and certainly more "OO") way is Mike's "Visitor" pattern.

However, there's yet another possibility, which is the "subscriber" pattern implemented in JMS (which is basically a damn great queue), which allows recipients to register their interest in messages independently of their creators. It basically works like this:
1. You have a Queue (or QueueManager) that knows about ALL types of messages (or knows how to find out what they are). If a message doesn't have a valid type, or it's not created by a registered Creator, it's not allowed on the queue. It also doesn't allow anyone who isn't registered as a Recipient to read anything.
2. When a Creator creates a message, they mark it "for anyone interested in" type1, type2 ... and so on.
3. When a Recipient registers with the Queue, they state explicitly what types of messages they're interested in: type1, type16, etc.

As you can imagine, this makes for a very flexible model that allows creators and recipients of messages to be completely decoupled, and allows recipients to "log in" and "log out" of a Queue any time they choose.

I should add that I may have the type names different from the "official" pattern (I think they use terms like 'Source' and 'Target'); but it's the way I think about it.

HIH

Winston
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
+1 for the Subscriber pattern. I've used that recently and it makes it very easy to add new functionality. If you have a core routing/processing framework for the messages you just need to write a new producer and a new subscriber (again I'm not sure on the standard pattern names here). It completely decouples production of the messages from the delivery, and delivery from the processing.
 
Sreeni Nair
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you all for the responses. I decided to go with the Visitor pattern, finally. This does not merit the registration etc as this is a simple system with 3-4 message types, and will remain so forever. Moreover, I'm rewriting some existing code to make it cleaner, so the Visitor pattern suits perfectly. The only thing that is still nagging me a bit is that by using the Visitor pattern, I forced the consumer thread to expose some methods. My ideal solution would have been messages that are a public, a queue that is shared and public, and a totally-black-box implementation of the consumer, if it makes sense. But, the Visitor pattern is a worthy compromise. Thanks, once again.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!