I am using javax.jms.Connection to send and receive JMS messages to/from JBoss501. I am also using the Connection.setExceptionListener(). I would like to know if the exception listener needs to be set before the connection is started by Connection.start()? Any ideas to reproduce the JBoss connection exception at will to confirm if the exception listener is invoked.
From the spec:
If a JMS provider detects a serious problem with a Connection object, it informs the Connection object's ExceptionListener, if one has been registered. It does this by calling the listener's onException method, passing it a JMSException argument describing the problem.
An exception listener allows a client to be notified of a problem asynchronously. Some connections only consume messages, so they would have no other way to learn that their connection has failed.
Remember that there is place for vendor specific implementation here, about how exceptions are handled. Some vendors try to "fix" the situation if possible.
Now about start the connection before or after setting the exception listeneer...
Always set the exception listener BEFORE starting the connection.
And About reproducing I think you could
Start a consumer, connection.start should be run. And waiting for a message.
Shutdown jboss immediately.
Restart jboss.
Also I know that using Eclipse or other dev tools will help you start in debug mode, and you can at any specific time as the debugger shows you the status just abort the jboss server and restart it again.
With Jboss 5.0.1, setting the exception listener worked even after starting the connection. As mentioned by "MrSimpleMind" exception listener serves better before starting the connection - in fact - best as soon as the connection is created from ConnectionFactory.
The exception listener is effective even if the connection is not started - in case of Jboss 501.
//Main
try {
connection = getConnection();
connection.setExceptionListener(new MyExceptionListener());
//Exception listener is effective even before connection is started.
//connection.start();
while(true){
try {
Thread.sleep(1000 * 5);
Log.l("Kill the JMS provider any time now. !! Observe if the JMS listener works.");
} catch (InterruptedException e) {
//do nothing.
}
}
} catch (NamingException e) {
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
}
//Exception Listener
public class MyExceptionListener implements ExceptionListener {
#Override
public void onException(JMSException e) {
Log.l("Exception listener invoked");
}
}
To reproduce the scenario where the ExceptionListener gets triggered/invoked, I used the JBoss Management console and stopped the ConnectionFactory using the mx bean exposed by Jboss mgmt console.
Related
I have checked some of the Java RMI examples. But none of them demonstrate how to recover from a potential server failure, or a RemoteException, which might be thrown from the remote interface we define. And I couldn't find any relevant information either.
For instance,
public static void main(String[] args)
{
try
{
Server server = new Server();
Hello stub = (Hello) UnicastRemoteObject.exportObject(server, 0);
Naming.rebind("rmi://localhost/Hello", stub);
System.out.println("Server is up.");
}
catch (RemoteException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
After the exception is caught, the server just exits. Is here the intent for the server to die when such exceptions are thrown? Can we recover from such failures, like restarting the server? But how?
Thank you,
-----------Updates----------
To clarify, initially, I thought the RemoteException specified in the remote interface might be caught here. But after some experiments, I find they will actually show up on the client side and should be handled by the client.
Your RMI server only throws that exception at initialisation / start-up in UnicastRemoteObject.exportObject or Naming.rebind. The chances are that any error here isn't recoverable simply by running a loop to perform the same action again. There is some other problem to investigate.
If you server gets past the exportObject/rebind you see the "Server is up" message, the execution passes through the catch block and main(String[] args) ends normally. Even the thread handling [main] probably ends here.
But, the JVM process does not exit as there are non-daemon threads running. Any exceptions in the server are not passed back to the catch(RemoteException e) block shown in your main because main() has ended already.
In live systems I've observed several measures used by developers to counter issues found with RMI servers:
server startup scripts use limited loop to retry startup if it dies (this is more effective if it dies after long period not if fails instantly)
periodic round trip rmi client to server calls with trivial operation to prove RMI server health
run multiple instances of rmi servers with deliberate shutdown restart cycles at different time to ensure 100% operation
process monitors on rmi servers => trigger alerts for manual intervention
Most importantly you need effective logging so you can diagnose why it died afterwards.
I have a Docker container with a Java application that uses a DB to persist some data. My application has a class that extends another one that is not code of mine (specifically SinkTask, a class from Kafka that is used to transfer data from Kafka to another system). When the application starts it opens a connection to the database. Sometimes, the database closes the connection and tasks start to fail. The exceptions thrown by these failures are catched in one part of my code and I can think of different ways to handle them:
1. Simply executing the code from within the application that stops and starts the connection again
2. Restarting the Docker container, creating a new connection in the process
I think the best solution is number 1. However, I wanted to know how could I trigger the second situation. My guess is that I should throw a new Exception in the catch block capable of terminating the application (remember that the SinkTask part of the code is out of my control). Would this be a good solution? Which kind of Exception should I throw in this case?
This is the part of the code where I catch the exception
private void commitCollections() {
for (SinkCollection sc : collections.values()) {
try {
commitCollection(sc);
} catch (Exception e) {
LOG.error("Error flushing collection " + sc.getTableName(), e);
}
}
transactionRecordCount = 0;
try {
connection.commit();
} catch (SQLException e) {
LOG.error("Commit error", e);
}
}
Throwing an Exception and letting it propagate in order to terminate the application is a perfectly nice solution. IMO, using System.exit(exit_code) would be better because it clearly describes what that code is doing.
In addition, docker will display the exit_code in the status of the container (docker ps -a), thus helping differentiate between different error conditions. When an uncaught exception is thrown the exit code is always 1.
Hope that helps.
I am using IBM MQ-7.5. I am running a jms client which connects to the manager running on some other hosts.
I want to monitor the TCP connections with the manager. How do I get notified if my client connection is broken with the manager ? Is there any callback or listener provided in IBM MQ APIs to know any interruption on connection ?
Eg. Like ActiveMQ has http://activemq.apache.org/maven/apidocs/org/apache/activemq/transport/TransportListener.html
Thanks,
Anuj
In terms of connections being dropped a connection broken exception will be sent via the exception listener.
The JMS Specification is written such that events such as connection broken are legitimately returned on synchronous calls only. I would also recommended setting an exception listener, and to catch exceptions from all messaging operations and taking appropriate action.
Do you want to monitor client application connections at the queue manager end or in the client application?
To get notified of any connection issues, MQ JMS client has an ExceptionListener that can be attached to MQConnection. This exception listener will be invoked when there is an issue with connection to queue manager, for example connection to queue manager is broken. More details here: View details of setExceptionListener method. Call the setExceptionListener method on MQConnection to register a callback as shown below.
MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
ExceptionListener exceptionListener = new ExceptionListener(){
#Override
public void onException(JMSException e) {
System.out.println(e);
if(e.getLinkedException() != null)
System.out.println(e.getLinkedException());
}
};
MQQueueConnection connection = (MQQueueConnection) cf.createQueueConnection();
connection.setExceptionListener(exceptionListener);
To actively check the health of connection and session, i am thinking of using below approach.
/**
* Method to check if connection is healthy or not.
* It creates a session and close it. mqQueueConnection
* is the connection for which we want to check the health.
*/
protected boolean isConnectionHealthy()
{
try {
Session session = mqQueueConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
session.close();
}
catch(JMSException e) {
LOG.warn("Exception occured while checking health of connection. Not able to create " + "new session" + e.getMessage(), e);
return false;
}
return true;
}
/**
* Method to check if session is healthy or not.
* It creates a consumer and close it. mqQueueSession
* is the session for which we want to check the health.
*/
protected boolean isSessionHealthy()
{
try {
MessageConsumer consumer = mqQueueSession.createConsumer(mqQueue);
consumer.close();
}
catch(JMSException e) {
LOG.warn("Exception occured while checking health of the session. Not able to create "
+ "new consumer" + e.getMessage(), e);
return false;
}
return true;
}
Does it approach looks good ?
I just have one fear here:
I am creating a test session in isConnectionhealthy() method and closing it. Will it not affect the already created session which is actually used for real communication? I mean will it do something like it closed already created session and started new one ?
I have a simple database connection method that I want to add a condition that if the connection fails then an email is sent to a list of people telling that it failed to connect.
My current method is this:
public Connection createInitialConnection() throws ClassNotFoundException, SQLException, PollingException
{
DBConnectionDetails conDetails = new DBConnectionDetails("INITIAL");
Class.forName(conDetails.getDriver());
Connection connInitial = DriverManager.getConnection(conDetails.getUrl(),
conDetails.getUser(), conDetails.getPassword());
logger.info("Initial connection created" + conDetails.getUrl());
return connInitial;
}
Currently, there is no checking to see if the connection was successful, if it does not connect then the program just keeps going.
I'm not sure about the best way to do this would be. An if/else or try/catch?
Logging libraries like log4j allow you to add a logging appender that sends emails for each log entry (of course you can filter by severity, category, etc.). So when you attempt to get a connection and an exception is thrown it should get caught by the exception handler and logged, and the logger will send emails.
That assumes your application has some kind of exception handler that logs uncaught exceptions. Where that happens depends on your application's architecture. It could be in a servlet, in try-catch code in the jsp, or in a dedicated handler in a webapp framework like struts or spring-mvc.
If you implement this you will have a way to be notified when any exceptions are getting logged, it won't be limited to database connectivity problems.
You can send email on catch block.
try{
Class.forName(conDetails.getDriver());
Connection connInitial = DriverManager.getConnection(conDetails.getUrl(),
conDetails.getUser(), conDetails.getPassword());
}
catch(SQLException | ClassNotFoundException ex){ // Java 7 needed for multicatch
// Send the Email.
}
Maybe you should try to catch SQLExcepton and then, send notification like this :
try {
Connection connInitial = DriverManager.getConnection(conDetails.getUrl(), conDetails.getUser(), conDetails.getPassword());
} catch (SQLException e) {
//send notification here
}
catch block. It is always better than if-else
try{
// your Logic to test the connection
}
catch(Exception ex)
{
//Code to send the mail if the connection is failed.
}
You can do with try { } Catch .. This in case you have an execption like no network or somthing. after that you need to check if Connection != null.. This is all you need
Sending an email in the catch block might be OK for your application, but then you're faced with how to configure the email. Who should receive it? Are multiple recipients possible? How should the senders, subject and format be configured and passed to your mailer? What if the mailer fails? You may find yourself reinventing an existing solution if you go that route.
If you're using Log4j, it might be a good idea to configure a SMTPAppender for your existing logger or create a logger for errors which need to be sent over email. You can configure Log4j to use the appender for only SQL exceptions if you like (ie. log4j: Log output of a specific class to a specific appender).
I am currently setting up a Tomcat Server that is running an embedded ActiveMQ broker. I'm using Spring to configure JMS. I wrote a test application to listen to topics and when I exit the test application the ActiveMQ broker throws a SocketException. Here is the exception:
2009-06-09 13:12:48,005 DEBUG Transport:229 - Transport failed: java.net.SocketException: Connection reset
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at org.apache.activemq.transport.tcp.TcpBufferedInputStream.fill(TcpBufferedInputStream.java:50)
at org.apache.activemq.transport.tcp.TcpBufferedInputStream.read(TcpBufferedInputStream.java:58)
at java.io.DataInputStream.readInt(DataInputStream.java:370)
at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:269)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:210)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:202)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:185)
at java.lang.Thread.run(Thread.java:619)
My test application just loads the context xml file, loops sleeps every 60 seconds.
public static void main(String[] args) {
long numMillisecondsToSleep = 60000;
new ClassPathXmlApplicationContext("client-context.xml");
while (true) {
try {
logger.info("Sleeping for 60 seconds");
Thread.sleep(numMillisecondsToSleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I was wondering if anyone might know why I'm getting this exception. I'm very new to ActiveMQ and JMS in general so any ideas would be greatly appreciated.
I think there's a way to shut down an embedded broker nicely via a method call. Posting your config along with your embedding code will help people figure out what's going on.
I would recommend looking in to Spring's JmsTemplates; it wraps all of the complexity of MQ into a nice package and ensures little errors like this dont cause you hours of problems.
http://activemq.apache.org/spring-support.html