Java Forum / General / March 2006
MessageDrivenBeans
Jesus M. Salvo Jr. - 23 Feb 2006 13:50 GMT I am investigating the use of a J2EE container ( JBoss, etc. ) for the sole purpose of using MessageDriveBeans as JMS consumers.
Is it possible for multiple instances of a container ( one on each machine ) to be consuming from the same JMS queue ( persisted to the same database ??? )
robert - 23 Feb 2006 16:43 GMT > I am investigating the use of a J2EE container ( JBoss, etc. ) for the sole > purpose of using MessageDriveBeans as JMS consumers. > > Is it possible for multiple instances of a container ( one on each machine ) > to be consuming from the same JMS queue ( persisted to the same > database ??? ) You would use publish / subscribe for that, right? Use a topic, not a queue. Each mdb subscribes to the topic. The persistence has nothing do with it, besides of course the durability. JBoss has some quirks doing remote topics / queues, but after a bit of pain it does work.
HTH, Robert http://www.braziloutsource.com/
Raymond DeCampo - 23 Feb 2006 18:27 GMT >>I am investigating the use of a J2EE container ( JBoss, etc. ) for the sole >>purpose of using MessageDriveBeans as JMS consumers. [quoted text clipped - 7 lines] > with it, besides of course the durability. JBoss has some quirks doing > remote topics / queues, but after a bit of pain it does work. Reading carefully, I think the OP does want a queue. That is, he only wants one consumer of each message. The crux of his question is can many consumers, in the form of MDBs running on different JVMs/machines, consume messages from the same queue.
Yes, this is possible. Common ways that application servers will support this include the following. One way is by clustering the application server, so that many application servers appear logically as one application server. Another way is to configure some of the application servers to utilize another application servers JMS queue.
HTH, Ray
 Signature This signature intentionally left blank.
robert - 23 Feb 2006 21:14 GMT > >>I am investigating the use of a J2EE container ( JBoss, etc. ) for the sole > >>purpose of using MessageDriveBeans as JMS consumers. [quoted text clipped - 21 lines] > HTH, > Ray We might be talking to ourselves here ;-) , but couldn't threads due that as well?
// must have seperate threads - with a seperate session - for every listener (new Thread(new QueueListener(0, file_queue))).start(); (new Thread(new QueueListener(1, file_queue))).start(); (new Thread(new QueueListener(2, file_queue))).start(); (new Thread(new QueueListener(3, file_queue))).start();
//Inner class static public class QueueListener implements MessageListener, Runnable { private int threadCount = 0; private int index = 0; private Queue queue;
public QueueListener(int _tc, Queue _q) { this.threadCount = _tc; this.queue = _q; }
public void onMessage(Message message) { try { // do something } catch (Exception e) { e.printStackTrace(); } }
public void run() { try { synchronized(this) { this.index++; } QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueReceiver queueReceiver = session.createReceiver(this.queue); queueReceiver.setMessageListener(this); System.out.println ("Running QueueListener on queue: " + this.queue.getQueueName());
while (true) { Thread.sleep(500); // keep the thread alive so that the // session doesn't get garbage-collected } } catch( Exception e ) { e.printStackTrace(); } } }
I do this often for testing several different queues (instead of just file_queue, smtp_queue) etc. Just curious if what you describe would work with the code above.
Robert http://www.braziloutsource.com/
Raymond DeCampo - 24 Feb 2006 13:22 GMT >>>>I am investigating the use of a J2EE container ( JBoss, etc. ) for the sole >>>>purpose of using MessageDriveBeans as JMS consumers. [quoted text clipped - 90 lines] > file_queue, smtp_queue) etc. Just curious if what you describe would > work with the code above. I am never found it necessary to explicitly manage the threads for listening for JMS messages. In your code you neglected to invoke connection.start(); perhaps a transcription error.
I am also suspicious of the while(true) loop you have that does nothing. Basically you are incurring the cost of a thread just to keep a local variable from being garbage collected. (Further, I would argue that a really smart GC could garbage collect that variable anyway, since it is not referenced anywhere forward in the code.) You could avoid this by making the variable an instance variable.
Ray
 Signature This signature intentionally left blank.
iksrazal@gmail.com - 01 Mar 2006 12:14 GMT > > I do this often for testing several different queues (instead of just > > file_queue, smtp_queue) etc. Just curious if what you describe would [quoted text clipped - 12 lines] > > Ray Been reflecting on your comments a bit and I hope you appreciate that I'm just trying to learn. The jist of what I was trying to show is that, while having multiple consumers on a single queue is rare or perhaps a bit specialized, it is possible with merely a few lines of code using threads, ie no cluster.
The point of the threads is that:
1) A seperate session is needed for every listener. That's easy to manage inside run() via connection.createQueueSession() . 2) Minor advantage using non-daemon threads to keep the queue listeners running. 3) Threads are light weight, whereas what is done inside onMessage() may not be.
Done that way of course has only, I'm thinking, the advantage of parallel processing. And nothing to do with the OP question of redundancy.
I think your caveat was that 'QueueSession session' should be an instance variable of the inner class. If so, I appreciate the tip.
Oh yeah - the jboss remote queue ' connection.start() ' initialization is as such:
private static final String QUEUE_FILE_SCHEDULE = "queue/FILE_SCHEDULE"; Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties.put(Context.URL_PKG_PREFIXES, "org.jnp.interfaces"); properties.put(Context.PROVIDER_URL, "localhost");
InitialContext context = new InitialContext(properties); // UIL2 is the only external client connector Object tmp = context.lookup("UIL2ConnectionFactory"); QueueConnectionFactory factory = (QueueConnectionFactory) tmp; connection = factory.createQueueConnection(); connection.start();
Queue file_queue = (Queue) context.lookup(QUEUE_FILE_SCHEDULE);
Hope this advances the conversation.
Robert
Raymond DeCampo - 11 Mar 2006 19:00 GMT >>>I do this often for testing several different queues (instead of just >>>file_queue, smtp_queue) etc. Just curious if what you describe would [quoted text clipped - 18 lines] > perhaps a bit specialized, it is possible with merely a few lines of > code using threads, ie no cluster. Having multiple consumers on a single queue is far from rare or specialized. Queues were designed for multiple consumers. The difference between a topic and a queue is only relevant when you have multiple consumers.
> The point of the threads is that: > > 1) A seperate session is needed for every listener. That's easy to > manage inside run() via connection.createQueueSession() . This has nothing to do with threads. Maintaining a separate state for different objects is a very basic functionality provided by any OO language.
> 2) Minor advantage using non-daemon threads to keep the queue listeners > running. Your threads do not do that. The threads you posted simply do busy cycle wasting.
> 3) Threads are light weight, whereas what is done inside onMessage() > may not be. ???? If you need a thread to handle onMessage() tasks, that would be the time to create it.
> Done that way of course has only, I'm thinking, the advantage of > parallel processing. And nothing to do with the OP question of [quoted text clipped - 17 lines] > // UIL2 is the only external client connector > Object tmp = context.lookup("UIL2ConnectionFactory"); My recollection of the JBoss documentation is that it is recommended that you access the connection factory at java:/ConnectionFactory, even externally. (I have applications that do this successfully.)
> QueueConnectionFactory factory = (QueueConnectionFactory) tmp; > connection = factory.createQueueConnection(); [quoted text clipped - 5 lines] > > Robert Ray
 Signature This signature intentionally left blank.
Jesus M. Salvo Jr. - 25 Feb 2006 04:00 GMT > Reading carefully, I think the OP does want a queue. That is, he only > wants one consumer of each message. The crux of his question is can [quoted text clipped - 9 lines] > HTH, > Ray Hi Ray,
Sorry for the late response ...
Assume for the moment that I don't want to use clustering ( which leaves out the first option ), but still want the ability to avoid a single point-of-failure ( which then also leaves out the second option, since if the "another application server" goes down, the other app servers using that "another application server's" JMS queue ).
What I have is a database that already has auto-failover, which I thus want to use as the underlying persistence for the JMS queue(s).
Does any JMS provider allow multiple instances of JMS provider(s) on difference machines to use the same physical destination ??
Raymond DeCampo - 25 Feb 2006 19:50 GMT >>Reading carefully, I think the OP does want a queue. That is, he only >>wants one consumer of each message. The crux of his question is can [quoted text clipped - 25 lines] > Does any JMS provider allow multiple instances of JMS provider(s) on > difference machines to use the same physical destination ?? Respectfully, what you are asking for does not make sense. The physical artifacts in the DB that a JMS server uses to persist state are not meant to be shared with other JMS servers. You could probably configure the app servers to do what you say, but the results would be unpredictable. For example, I would expect to see messages delivered twice in a queue among other anomalies. (I suppose it is possible that a particular JMS server could be implemented in such a way as to allow this, but unless it is specifically documented, I wouldn't depend on it.)
The fact that the database has auto-failover is nice, but it does not give you a way to piggyback upon that automatically eliminate single points of failure. The way to do that with J2EE is to cluster the application server, a service which all application servers provide.
HTH, Ray
 Signature This signature intentionally left blank.
Jesus M. Salvo Jr. - 28 Feb 2006 12:00 GMT >>>Reading carefully, I think the OP does want a queue. That is, he only >>>wants one consumer of each message. The crux of his question is can [quoted text clipped - 34 lines] > a particular JMS server could be implemented in such a way as to allow > this, but unless it is specifically documented, I wouldn't depend on it.) Thanks .... at least you understand the question that I had.
Having said that, even if the appservers were clustered, wouldn't the JMS provider on each node simply do a SQL select from the same underlying tables ( and perhaps lock the rows that it selected ) ??
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|