Good question! When I got to work with it, it took me quite some time to under stand it also.
I assume we talk about Universal Distributed Queues or Topics. (You want a topic, but it applies similarly to Queues).
Let me for asume Universal Distributed Queues for a moment.
A Queue is a logical object. A JMS Client makes a connection to a Weblogic server that makes this logical object available. But in Weblogic JMS it has to be implemented or serviced by a more 'physical' object a JMS Server. A JMS Server defines how queues are persisted: in memory, in file, or in the database. This is done by defining a filebased or jdbc based persistence store, or no persistence store at all.
A JMS Server is a singleton object and can run to only one Weblogic Server at a time. You can target it to a migratable target, but that only means that it will be moved to another Managed Server at failure.
A Universal Distributed Destination (Queue or Topic) can be targetted to multiple JMS Servers. That way a UDQ or UDT can be serviced by multiple Managed Server.
But now it comes: a message enqueued on a queue or topic, is to be guaranteed to be delivered once and only once. Weblogic JMS is designed to prevent message duplication.
To do so, for a client to connect to a Queue, it has to connect to a managed server first. Then it can get a Connection Factory and a Queue over JNDI. And then connect to the particular Queue. If the client is a producer, it produces messages to the JMS Server. The messages need to land to only one JMS Server, because of the once-and-only-once delivery. To be a bit more precise: a Universal Distributed Queue acts to the JMS Client as a single Queue, but is implemented as a local member queue to the JMS Server. Every JMS Server has it's own implementation of that same queue. You can navigate to the Admin Console -> Services -> Messaging -> JMS Modules -> Queue or Topic -> Monitoring tab, and you will see a member queue per JMS Server that this queue is targetted to.
So, Weblogic connects the client to a JMS Server. Which one, do you think? Now, that depends. If the jms client is remote to the Weblogic Server, running in it's own JVM, outside of Weblogic Server, it will connect to one of the JMS Servers in the cluster round robin. (By the way, a JMS Client running on a Weblogic Server, that does not have a JMS Server with this queue as a target, can be considered as remote.) Every time it does a reconnect and recreates a queue session, it gets connect to another local member queue of another JMS Server. And every message produced in that session lands on the local member queue of that particular JMS Server.
However, if the client is running within the Weblogic Server, Weblogic will allways connect the JMS client to the local JMS Server, unless the JMS explicitly requests otherwise (by specifying the JMS server using an @ sign. Thus, by default, every message produced by a JMS Client within the Weblogic Server, will land on the JMS Server running on that same Managed Server.
Consuming the messages will work the same way: remote JMS Clients will consume messages from the JMS Servers round robin while JMS Clients within the Weblogic Server, will only consume messages from the 'local' JMS Server.
The same counts for Topics, because also for a topic with a Durable Subscriber, it has to be guaranteed that every subscriber gets the message once and only once.
Thus to be able to consume every message produced, you need to make sure you have (durable tobic subscriber) consumers connecting to every servicing Weblogic server.
In the past I needed a service that did a JMS get for messages based on a correlation Id. If it did not got the message it had to look for the message in another JMS server. I used jmx to query all the jms servers in the domain, and then queried for the JMS message on every one of those using the @ notation.
In Java you can specify the queue using:
String jmsSvrQueueJndi = jmsServer +"@" +queueJndi;
In you case with OSB, you should make sure that you have a JMS Server on every OSB Server. Unfortunately, using the JMS transport you need to specify a comma separated list of JMS Servers on specific OSB Servers, or using different endpoints per OSB Server. You should use Customization files to update those with every OSB server in the cluster for the particular target environment. Or use a smart WLST script that update those.
You can also use the Oracle SOA JMS adapter instead of the JMS Transport. Using that, you don't need to provide the endpoints: the JMS Adapter will query it from Weblogic using JNDI.
Hope this provides some insight.
Thanks for shedding some light into the Universal Distributed Topic darkness
So if I understand correctly......
-You need to have the JMSServer deployed on every managed server...check
-For durable subscribers (not running on the specified weblogic env) you need to connect to every managed server using the @
-For durable subscribers (running on the specified weblogic env) it wil just connect to the local managed server but you still have to connect using the @
We have customizations to add the different managed servers in the endpoints to read using a JMS businesss service for example jms://--OSB-MS1--,--OSB-MS2--,--OSB-MS3--,--OSB-MS4--,--OSB-MS5--,--OSB-MS6--/jms.EventCF_v1.0/EventJMSServer1@jms.EventTopic_v1.0
but I cannot add more JMSServers here....as you can see above we have EventJMSServers1 to 6. Can you set more endpoint uri's using Routing Options?
same goes for a business service subscribing to the different JMSServers in OSB... we use jms://127.0.0.1:7010/jms.EventCF_v1.0/EventJMSServer1@jms.EventTP_v1.0 but I cannot add mutliple JMSServers here or add multiple Endpoint URI's
Thanks in advance!
For durable subscribers (not running on the specified weblogic env) you need to connect to every managed server using the @
No, not really. But if you connect to a weblogic server and query for a queue/queue session from the JNDI tree, it will round robin get you a local queue member. If you reconnect, you'll get another, and another, until you get to the first one. Only if you explicitly want to get messages from a queue member on a specific JMS Server, then you use the @ sign.
For durable subscribers (running on the specified weblogic env) it wil just connect to the local managed server but you still have to connect using the @
No, not really. For jms clients (subscribers) running on the same weblogic server that has a JMS Server serving that queue, if you ask for the queue, you'll get the local queue member of the JMS Server running on that weblogic server. Again, only if you specifically want to get messages from a JMS server on another Managed server, then you use the @ sign.
The premisse in an OSB cluster is that every service is running on every OSB server within the cluster. Every OSB Server will have a JMS Server, and every service will connect to the JMS Server running on the same OSB server, the particular service instance runs on. That way you can produce to and consume from every local member.
You can have an JMS Service end-point, in a comma separated way:
Or, you can provide multiple endpoint uri's separately on the Business Service:
As said, you don't need to specify a jms server. You connect a managed server, and ask for a connection factory and a queue.
Yesterday, I had an interesting thought, that I haven't tried out in the past, and I don't have the abillity to test.
But from my story above, let's say you have 2 managed servers, and you provide 2 endpoints:
One of them is the osb server serving the thread running the particular osb service. Then the service will 'round robin'-ly connect to either of them, one of them being the local osbserver. If it is the osbserver1, it will by default get the local queue-member. But when it connects to osbserver2 it is remotely to osbserver2, because it runs on osbserver1.
Now, osbserver2 will deliver a connection to it's own jms server, but it might also provide a connection to a jmsserver not running on itself. Now, imagine you add a managed server osbserver3 to the cluster and create an extra JMS server (EventJMSServer3) for it. But you do not add it to the endpoints. Then I would expect that when a thread on osbserver1, connects to osbserver2, it might also get messages from or produce to EventJMSServer3. It would be interesting to try that out. But again, I'm not sure.
Honestly, I would think that I would try the JMS adapter in your case.
Yep I think the JMS adapter is my best bet. Thanks for some clarification!