Even if it's ok to open a socket inside a Bean, this is not allowed by the spec.
Why not creating an MBean that listens to your queue and sends info to the socket. If socket failed at some point, you can update the state of your mbean and close your JMS connection till your socket is back. When your socket is back you can reinitialize the JMS session.
Does it help?
So you mean I should put my message listener class inside of the JBOSS config files and deploy it? How can I update the state of the MBean?
I am not entirely familiar with MBeans. Is that a message driven bean?
And is it still a possibility to stop a queue connection from within a message listener? Another possibility would be to throw an exception that maybe the queue receiver class that it's registered with could catch and then stop the connection.
No. If you want to react synchronously you should read the queue synchronously as well. However, as you can ADD a listener to a queue you could also remove it normally (I never tried that listener thing so I can't confirm, check the Javadoc).
An MBean is not a MDB. This is a management object which allows you to do multiple things that J2EE business objet are not supposed to do by themselves (i.e. open a socket)
Check if you can remove the listener on your session
Well, you can supposedly set the message listener to NULL and that is the equivalent of unsetting the listener. I however cannot get this to work. Every time I send a message to the queue it still calls the onMessage() method of the listener.
The problem is that my listener is passed in a socket channel. It then uses the socket channel to send the message to another application. This "send" is where I would get a socket exception. I need the Queue Receiver class to then unset the listener temporarily or stop the connection so it doesn't keep consuming messages. It's not working.
Since using a socket inside of a message driven bean is not in the spec, what is the correct thing to do with the message? Look up another program in JNDI? Other people must have this same problem.
So presumably your setting up your listener something like the following:
String queue = "queue/listenerQueue";
String ConnectionFactory = "ConnectionFactory";
Queue q = (Queue)ctx.lookup( queue );
QueueConnectionFactory qcf =
(QueueConnectionFactory)ctx.lookup( connectionFactory );
QueueConnection qcon = qcf.createQueueConnection();
QueueSession session = qcon.createQueueSession( false,
QueueListener listener = session.createListener( q );
Adding the following method called when you blow up trying to send on the socket channel doesn't disconnect you from the Queue?
public final void stop()
listener = null;
> Since using a socket inside of a message driven bean is not in the spec, what is the correct thing to do with the message?
Use a JCA adaptor that could do that kind of things or, as I already told you, use an MBean. You don't need to use an MDB to process a JMS message
That's my first point. My second point is: if you want to be able to stop consuming message, then you should consume them synchronously (through a QueueReceiver.receive(timeout)). That way you can stop the reception of message(s) if something happenened (socket timeout or other event). If you have a transactionnal session and the problem occured while you got a message you can simply rollback the session for that message and you have transaction context as well.
Are you agains using an MBean? Do you think it's not the right solution? Maybe my explanations are not clear enough.
Opening a socket through a MDB is hazardous and shouldn't be done if another solution is available.
Let me know if you need more details (in the case you agree with my solution, or at least if you are convinced)
Yes, I understand. Using a queueReciever.receive() will give me better control of the situation. If the socket dies I can stop the connection more gracefully. I started with this implementation but ran into problems. I will give it another try.
Are there any speed differences between using a listener or using receive()? One seems to 'pull' the data and the other 'pushes'.
thanks again for your help.
To answer your initial question, you can stop the
message listener thread by doing
It is likely that when you invoke stop() there is
already a message inside the session in the process of delivery
which is why you see delivery after stop().
You shouldn't see more than one message.
Both do push() and pull(), receive uses less threads.
T1 receive() -> server (no message return and wait)
T2 server -> delivers message
T1 receive() returns
T1 mainThread registers MessageListener
T2 messageListener receive() -> server(no message return and wait)
T3 server -> delivers message)
T2 messageLister -> onMessage()