JMS catching when a JMS server goes away - java

When there is a network problem which results in the client being disconnected from the JMS server, is there some other way to detect the problem other than waiting until the next JMS message being sent fails?

You can register an ExceptionListner with the JMS Connection using Connection.setExceptionListener(ExceptionListener)
The ExceptionListener will get notified of more problems than an actual disconnection, so you may have to filter the JMSException that gets passed to the listener.

ExceptionListener isn't necessarily enough. You also need to catch exceptions on any JMS calls you make (sending messages, for example). See Reconnecting JMS listener to JBossMQ

if your are running on MQ and looking to solve this problem, install a local MQ instance. More license but you will get guaranty delivery if your main corporate MQ goes down.
Other Option, use Spring and let the framework do the recovery of the connection.

Related

how to get notification from server when ever it is on

Is there any way to get notification from server whenever it is on?
my requirement is when ever ActiveMQ is on a piece of code will run automatically
in ActiveMQ is there is no load on startup
Create a publisher in your language of choice that periodically sends a test message to ActiveMQ.
Create a subscriber in your language of choice that receives the test messages and notifies you via your mechanism of choice that it has successfully received a test message.
The Apache ActiveMQ broker supports discovery with IP multicast.
Applications can use discovery for JMS clients to auto-detect a Message Broker to connect to.
This could also be used to monitor a broker's status, using Java MultiCast support.
To invoke a piece of code when the broker is started, you can perhaps base it off either an embedded Camel route or broker interceptor. The idea being that when the broker is started, so will these components and thus allows them to issue whatever sort of notification you require.

how to check if queues of the RabbitMQ server is alive

I am totally new to spring framework. I am trying to create a java maven project where I can have the connectivity to the rabbitMq and I even before publish the message, I want to check if the queues are alive or not. Is this possible to ping the queue to see if it a alive or not.. I am totally new to this rabbitMQ.
Thanks for the answers
Checking for the availability of a queue is a bit of an anti-pattern with messaging systems.
The message producer should not care if there is something on the other end to receive / process the message. The producer only cares that the RabbitMQ instance is available, with the correct exchange.
If the message must be delivered to a consumer, guaranteed, then the consumer needs to configure the queue with durability in mind and the producer should send the message with the persistence flag to ensure it is written to disk.
...
re-reading your question, i'm wondering if you mean "rabbitmq server" when you say "queue". are you wanting to check if the rabbitmq server is available?
if that is the case, the proper thing to do is use a heartbeat in your RabbitMQ connection. the spring framework should know how to do this, and should respond with some kind of event or other code that executes when the connection dies. i'm not really familiar with spring, though, so i don't know the details of doing that with this framework.
You might check this post or this RabbitMQ page on handling this.

How JMS client notice about new message

I'm learning JMS and wonder how a JMS client (e.g MessageListener) can notice about a new message in queue it registed. Is it frequently send requests to broker via TCP to see if there's a new message? If so, is this request synchronousor asynchronous?
JMS is just an API. It does not specify any wire level protocol. So you can't really tell how the client will behave with the broker. It could use a homing piegon for all we know. Ok, maybe not, but brokers like WebSphere MQ and ActiveMQ both supply in memory transport as well as TCP based.
Most vendors have thier own properitary protocols even though AMQP is visible on the horizon as a wire protocol standard (but far from all vendors have started to look at it).
When talking TCP there is no need to poll as long as there is a live connection going on. The broker can easily notify the client that there is a new message published while the client sleeps and the other way around.
A common way, however, is to actually do poll. But rather poll for consumer.receive(TIMEOUT); in some longer intervals (seconds). This makes it possible to use distributed transactions in frameworks like spring. Still the broker sends actual TCP messages to the client on demand.
If it would not have been like this, then JMS/Messaging would not have been such a fast, wide psread and scalable technology
1) First of all, JMS does not have something called absolute synchronous messaging. You can definitely implement so called JMS Synchronous messaging by implementing Sync service methods but in fact it just appears to be mimicking as Synchronous messaging. In fact it is also Async Messaging.
2) Technically it is the JMS Server / Broker which sends Messages to Message Consumers through dedicated queues. Broker simply delivers the message to Message Consumer's onMessage() method. And then Container executes onMessage() method.

How is it possible to reliably send JMS message? (fail over MessageProducer.send() errors)

Is it possible to reliably send JMS message to the destination? By reliably I mean ensuring that if e.g. MessageProducer.send() call fails for some reason, it will be retried automatically. I realize that transaction session may use .recover() as last resort, but what about retrying? E.g. I have intermittent network failure in between session was established and attempted to send a message. How would recover() help in this case?
As far as I know, JMS do not support such behavior. You could search among specific vendor-extensions but, IMHO, it is unlikely that you find something suitable to your needs.
I see only two solutions to your problem:
Implement it. You can manage the JMS session manually, catch any exception and, if needed, use "set rollback only" function of transaction manager to invalidate the transaction.
Use a local queue to store messages and use a background service to move them to target remote queue. Note that many queue manager support this, e.g. Store and forward Queues of ActiveMQ. Obviously this way, your transaction boundary will not include remote queue.
I know that 2nd solutions is not a full answer to your problem but, many times, it is sufficient.
JMS doesn't specify the behavior you are looking for. In fact, JMS specifically addresses problems due to network failure by noting that you may get the same message twice and calls this a "functionally duplicate" message since from the point of view of the JMS broker, it has only been delivered once.
Since this is not part of JMS your answer lies in the different vendor implementations. For example, WebSphere MQ has a feature called "Multi-Instance Queue Manager" as of v7.0.1. A v7.0.1 client application will automatically retry the connection and even follow the QMgr from the primary to the secondary node in the event of a failure. The application blocks while this occurs and is not aware of the failover.
However, even with this behavior, your app still needs to code for the failure. For example, if using the WMQ automatic reconnect (or any provider's reconnect for that matter) you probably want to tune the length of time the app might block waiting to recover the connection so that the user doesn't experience an indefinite hang. When the call unblocks, the transaction is rolled back and any retry must occur in the code. This is appropriate since the transaction is associated with a connection that is no longer valid.

How to design an MQ Server?

I'm unclear as to whether there should be a 1-1 or a 1-* relationship between:
Server-Connection Channel and JMS Topic
Server-Connection Channel and Listener
Listener and Topic
Regards the design of our application layer, there is a single MDB that in response to a message, does some work, then publishes messages onto a variety of output topics. The service layer is listening on these output topics.
Currently I have a 1-1-1 between Channel-Listener-Topic, and therefore an instance of JmsConnectionFactory for each publisher (on the app side) and listener (on the service side).
There are a couple of different ways to look at this. From the point of view of your application one connection factory can have many sessions. Each session may have many consumers but units of work are scoped per session, not per consumer. So more than likely you want one connection factory with multiple sessions where each session has a listener on a particular topic. If you have a listener assigned to multiple consumers on a single session, any acknowledge (or COMMIT in a transacted session) commits all messages got or put in that session.
From the WMQ server's point of view, one channel definition can have many running instances. So you only need the one SVRCONN channel defined per app, regardless of how many channel instances it needs to start. Try not to put different apps on the same SVRCONN though because you often want to administer or authorize the apps separately. For example, with apps on separate channels you could easily figure out which app was misbehaving if you suddenly found yourself with 3000 running channels.
For purposes of administration and debugging, I'd probably have one CF for the app side and one CF for the service side. Each would point to a different SVRCONN channel as described above. Inside the app server I'd stick with one topic per session unless it is valid for your app to consume off multiple topics in a single unit of work. In the subscription you can specify a wildcard topic to get all topics below a certain point in the topic tree with a single subscriber.
Just for best practices, I'd also set the CF to use FAILIFQUIESCE to make sure the QMgr can be stopped in an orderly fashion and I'd use SYNCPOINTALLGETS (or a transacted session with explicit commit calls) in order to improve reliability as per the JMS 1.1 spec, sestion 4.4.13 which states:
If a failure occurs between the time a client commits its work on a Session and the commit method returns, the client cannot determine if the transaction was committed or rolled back. The same ambiguity exists when a failure occurs between the non-transactional send of a PERSISTENT message and the return from the sending method. It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages.
A message that is redelivered due to session recovery is not considered a duplicate message.
The SYNCPOINTALLGETS (a.k.a. SPAG) insures that messages retrieved from the queue are delivered to your app before being committed and permanently removed from the queue. Otherwise if you lose your connection while the QMgr is trying to return a message, it's gone for good. With SPAG set you might see the same message twice as described in the JMS spec, but you'll never drop one.
For more details of the options available to the CF, queue and topic objects, see: Properties of objects in the WebSphere MQ Using Java manual.
WMQ v6.0 is end-of-life as of September 2012 so please be sure to develop using the v7 clients, even if the server is at v6. This will reduce your migration effort next year. Download v7 client here and the WMQ v7.1 client here.
An MDB in a container creates a pool of MDBs that concurrently process messages. If you simply process and write to the topic you will be fine. With this in mind you do not have a 1-1-1 relationship.
In your MDB just do a JNDI lookup of your TopicConnectionFactory and your Topic and then just write. Look here: http://middleware.its.state.nc.us/middleware/Documentation/en_US/htm/csqzaw09/csqzaw0931.htm

Categories