views:

52

answers:

3

I have a few clients that are both consumers and subscribers to a single topic on an ActiveMQ message broker. All the clients share the same code, they are in fact using exactly the same Enterprise Application consisting of: (1) an EJB producing a message, and (2) an MDB consuming the message.

The problem is basically that if I have clients A, B and C, and if A sends out a message, then A, B, C will all receive the message. I don't want A to receive its own message.

So I played around with various solutions, the best one I came up with was to set a string property on the outgoing message, e.g. source=myVeryOwnID. Then in the MDB, I set up a message selector like source <> 'myVeryOwnID'.

Unfortunately, that is a poor solution because I would have to set this ID in the source code (in my case, within annotations). This means that when deploying a new client, I cannot simply give the .EAR file to someone, instead I have to specifically re-compile with a unique "source" property.

Ideally, I would like to use the MAC address as the ID, or perhaps an ID set within Glassfish (I am using GFv3).

Any solutions or ideas would be highly appreciated!

+2  A: 

Using a "source" message attribute in the message and a message selector is IMHO the way to go. Now, if you don't want to hard code this in the MDB (in annotations), then use a deployment descriptor and set the message selector at packaging time.

Pascal Thivent
I thought about using a deployment descriptor too, but it leaves me with the same problem. I would have to build the same .EAR several times, i.e. one for each client.How about using a Connection Factory within Glassfish (with the ActiveMQ Resource adapter) and then setting "clientId" as a property. I need a clientId for my durable subscription, and it would be great to use it for my "source" property as well. However, I've been trying to do this and I'm not sure how to get the clientId from my factory.
T.K.
@T.K. The problem is just moved from compile time to packaging deployment time indeed (this might be a bit more handy, but not much) but this is how things were originally supposed to work: the "Application Assembler" had to set these kind of things when packaging and deploying component provided by the "Application Component Provider" (http://java.sun.com/javaee/5/docs/tutorial/doc/bnaca.html#bnach).
Pascal Thivent
A: 

What about the plain old System.GetProperty() and -D option? You can set the unique application ID as the system property:

-Dmyapp.id=A

For example in Tomcat you can pass system property via the JAVA_OPTS variable:

export JAVA_OPTS='-Dmyapp.id=A'

Then you can read it in the application:

String appId = System.getProperty("myapp.id")

All you have to do it to set system variable for each of your application server.

Henryk Konsek
I still don't see how it would work.
ewernli
The guy needs unique id per running application. He doesn't want to hard-code this id into the source code. Such kind of problems can be solved with System Properties set per running application (you pass id with -D option).And the minus is because of...?
Henryk Konsek
Henryk you are right. I upvoted you at least.
T.K.
He wants to filter the incoming message according to the application ID. I **still** don't see how a property help in this case (MDB `selector` can be either an annotations or a deployment config). @T.K. @Heenryk Can you please describe how you can solve the complete question with your approach?
ewernli
+1  A: 

ActiveMQ contains a method argument to address exactly this situation. Both the ActiveMQSession.createConsumer() method and the ActiveMQSession. createDurableSubscriber() method provide a variant that accepts an argument named noLocal. Set the noLocal argument to true to avoid receiving messages that were published locally on the same connection.

Bruce

bsnyder
Very good point. Thank you.
T.K.