views:

184

answers:

4

I have a queue of uniform message objects with multiple producers and a single consumer. The consumer is publishing the information and needs to be able to grant access based on the data's origin, so I want the producer send a suitable identifier along with the message. The producers themselves can't be responsible for the far side access restrictions.

The id should relate to the role of the producer in my application. I want to enforce that all producers have to define one and that a subclassed producer may choose to inherit or redefine it. The producer's class name would be a good approximation, but the property I want to identify is not really inherent in the class structure, it's rather something I define.

I could use reflection to find out the class name or maybe an interface name, but this smells of too much overhead. Also, I'm unsure what the appropriate property would be to look for.

As all producers subclass the same abstract parent class, I thought a good way would be to put a constant in there (or in an interface), but then I realised that in Java, a "constant" is really a "static final", which means I can't override it, so it doesn't work that way.

How would a more experienced Java programmer do this?

+6  A: 

If there's a "type" that you need to identify, define an interface that forces a class to give you that type, then implement that interface everywhere.

Example:

public interface IHasType {
   public String getTypeId();
}

However, if the list of types is fixed, I would go one step further and make the type an Enum:

public enum MyType {
   TYPE_A, TYPE_B;
}

And then return this enum instead of a String.

Jason Cohen
Should that be ICanHazType.
Tom Hawtin - tackline
I'm glad I'm not the only one thinking that ^
Joshua McKinnon
+1  A: 

Can the producer classes encapsulate the restrictions and "other things" in a method in themselves? That way each different producer could implement the appropriate method accordingly. Or just have that method return some sort of capability identifier, like an Enum of some sort.

If that won't work, like say if you want other consumers to do different things, then the obvious solution is to have a bunch of "if (object instanceof ....)" statements.

I've done it both ways, I can't say either is particularly "better" in all cases.

Paul Tomblin
I want the consumer to be responsible, so I can't put it in the producers. You could think of the producers to be "untrusted by design".
Hanno Fietz
A: 

First I think you need to be clear about what you are trying to protect against. Are you protecting against malicious code? If not, then just use the queued object.

If you want to protect against malicious code, then the obvious route would be to distribute a enqueueing object for each producer. No other producer should be able to get hold of another enqueuer, so you can trust anything added to the queue.

Tom Hawtin - tackline
No, there's no malicious code involved. My edit was in response to Paul Tomblin's answer, sorry if that might have caused confusion. I want the queued object to tell the consumer where it came from, so it's being processed correctly. I'll explain it better in the post.
Hanno Fietz
A: 

Have your message object extend java.util.EventObject, and have the message producer set itself as the message source. Then, the message consumer can just call getSource() on the message and find out who sent it. Of course, this assumes that you trust the message producers to properly populate this field.

Eddie
The mechanism is alright, but my question was how to translate source to the information I need. Does source implement an interface that tells me? Do I look at source's class? etc.
Hanno Fietz
The answer you selected http://stackoverflow.com/questions/606835/in-java-how-should-message-producers-identify-themselves/606848#606848 is a good way to get the information you need, either from the message object itself or from an EventObject source if you go that route.
Eddie
Thanks, Eddie. Actually, it's interesting how the answers sometimes bend the question towards what it should have been. If you look at the revision history, you can see how I tried to get closer to the point. Now that I have a solution, I know what my question really was.
Hanno Fietz