Author |
Message
|
speediii |
Posted: Mon Apr 24, 2006 10:40 am Post subject: MQ QueueManager fails to restart properly |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
Once I start my Java application then Stop the Queue manager and try to restart the QM again to test if reconnection works properly - the queue manager fails to restart with the following error:
"Error code 24 starting QM_TEST/Queue Manager Websphere MQ Service
The service was unable to start QM_TEST/Queue Manager. The error message reported was as follows: AMQ8041: The queue manager cannot be restarted or deleted because processes, that were previously connect, are still running. Process 9024 is still running. Process 19464 is still running. AMQ7018: The queue manager operation cannot be completed."
The process numbers are the windows mmc and java.exe processes.
I am pretty sure my code is correct as I open an mq connection, and upon receiving an exception I close the queue, perform mqmgr.disconnect (which fails with a 2059 & 2009 error as I stopped the QM), and try to reopen the connection with m_QMgr = new MQQueueManager(m_QMgrName);
There's a wait in there to stop it looping uncontrollably.
Any ideas what I'm doing wrong? It's somehow holding on to the MQ connection? I've tried using the connection pooling with:
MQPoolToken token=MQEnvironment.addConnectionPoolToken();
MQEnvironment.removeConnectionPoolToken(token);
And I've tried letting the Thread die and then restart the Thread, but the Qm still fails to restart. I perform an "Immediate" stop on the QM by the way.
Thanks in advance
Lee |
|
Back to top |
|
 |
speediii |
Posted: Tue Apr 25, 2006 12:15 am Post subject: Some more info: AMQ8041 |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
The AMQ8041 error means:
"AMQ8041 The queue manager cannot be restarted or deleted because processes, that were previously connected, are still running.
Explanation: Processes, that were connected to the queue manager the last time it was running, are still active. The queue manager cannot be restarted.
User Response: Stop the processes and try to start the queue manager."
If I stop the queue manager while my program is running, I would expect that by catching the Exception (on the next GET operation) and performing a .close() and .disconnect() on the Queue Manager should be enough to release any connection?
The only answer to this seems to be stopping my application and restarting it.
Lee |
|
Back to top |
|
 |
speediii |
Posted: Tue Apr 25, 2006 1:11 am Post subject: Still having trouble! |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
I extracted all the code to a simple test program, and I get the same error (ie A stop of the QM does not start again as the program does not release connected processes). Here's the code sample. If anyone has any ideas I'd really appreciate it. Thanks:
package com.test;
import java.util.*;
import java.io.File;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import com.ibm.mq.*;
public class MQTest{
static Logger log = Logger.getLogger(MQTest.class.getName());
protected static Logger rootLogger = Logger.getRootLogger();
private static String m_QMgrName = "QM_TEST";
private static MQQueueManager m_QMgr = null;
private static String m_QueueName = "LOQ.INPUT.1";
protected static MQQueue m_Queue;
static MQGetMessageOptions m_GetOptions;
public MQTest () {
}
protected static MQQueue openInputQueue(String queueName) throws Exception {
int options = -1;
options = MQC.MQOO_INPUT_AS_Q_DEF;
return openQueue(queueName, options);
}
public static MQQueue openQueue(String queueName, int options) throws Exception {
try {
return m_QMgr.accessQueue(queueName,
options,
null, // default QManager
null, // dynamic QName
null);// alternate user ID
} catch (MQException ex){
log.error("Failed to open queue["+queueName+"]");
throw ex;
}
}
public static void main(String[] args){
try {
System.out.println("MQTest");
useDefaultLogging();
m_GetOptions = new MQGetMessageOptions();
m_GetOptions.options = MQC.MQGMO_WAIT;
m_GetOptions.waitInterval = 5000; // 5 seconds - not (MQC.MQWI_UNLIMITED)
while (true) {
try {
m_QMgr = new MQQueueManager(m_QMgrName);
m_Queue = openInputQueue(m_QueueName);
log.info("CONNECTED to MQ Queue ["+m_QueueName+"] for Input.");
while (true) {
try {
com.ibm.mq.MQMessage msg = new com.ibm.mq.MQMessage();
//
//GET Message from MQ Queue
m_Queue.get(msg,m_GetOptions);
log.info("GET MQMessage - Message found");
} catch (com.ibm.mq.MQException mqex) {
if ( mqex.reasonCode == com.ibm.mq.MQException.MQRC_NO_MSG_AVAILABLE ) {
} else {
log.error("GET Exception:", mqex);
break;
}
}
}
} catch (Exception ex) {
log.error("Connect():", ex);
}
try {
m_QMgr.disconnect();
} catch (Exception ex) {
log.error("Disconnect():", ex);
}
wait(5);
}
}
catch (Exception e){
System.out.println("Could not start MQTest, exception " + e.toString());
e.printStackTrace();
System.exit(1);
}
} //End of main
static public void wait(int timeInSeconds) {
try {
//
//short wait
System.out.println("Sleeping for " + timeInSeconds + " second(s).");
for (int i=0;i<timeInSeconds;i++) {
System.out.print(".");
Thread.currentThread().sleep(1000);
}
} catch(Exception ex) {
System.out.println("ERROR:Error while sleeping Thread.");
ex.printStackTrace();
}
}
public static void useDefaultLogging() {
Logger log = rootLogger;
PatternLayout layout = new PatternLayout("%d [%t] %p - %m%n");
//
// CONSOLE Settings
ConsoleAppender app = new ConsoleAppender(layout, "System.err");
app.setTarget("System.err");
app.setName("ConsoleAppender");
log.getLoggerRepository().resetConfiguration();
log.setLevel(Level.DEBUG);
log.addAppender(app);
//
// FILE Settings
FileAppender fileAppender = null;
try {
fileAppender = new FileAppender(layout,"Default.log",false);
} catch(Exception e) {
log.fatal("Failed to set even the default Log4j settings!");
}
log.addAppender(fileAppender);
}
} |
|
Back to top |
|
 |
jefflowrey |
Posted: Tue Apr 25, 2006 4:49 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
There is some cacheing that goes on within the Java classes for connection handles. You have basically verified this yourself, but you can also see it by for instance rapidly connecting and disconnecting from a queue manager - you will see open connection handles remaining behind on the queue manager.
I don't know if this has been addressed in a fixpack of MQ or not, or if it's different in v6. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
speediii |
Posted: Tue Apr 25, 2006 6:50 am Post subject: |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
When I stop the Queue Manager my application does a .disconnect() on the Queue Manager object, But there's one mq process left called amqxssvn.exe
Shouldn't this process be released? The QM will not restart until I kill my java app and this process (after a short time) disappears.
I will try installing some fix pack to see if this issue goes away (aaarrggghh!) |
|
Back to top |
|
 |
jefflowrey |
Posted: Tue Apr 25, 2006 6:55 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
Yes, it should be released.
It isn't, because you haven't stopped the JVM and the connection handle is still cached behind the scenes - even though you've disconnected and probably even garbage collected the qmgr object. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
speediii |
Posted: Tue Apr 25, 2006 6:57 am Post subject: |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
I don't want to have to stop the JVM if some restarts the Queue manager. I want to be able to detect, release and poll for a reconnect.
Any idea how I can force this to be released? |
|
Back to top |
|
 |
jefflowrey |
Posted: Tue Apr 25, 2006 8:04 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
speediii wrote: |
Any idea how I can force this to be released? |
Open a PMR. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
RogerLacroix |
Posted: Tue Apr 25, 2006 10:05 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
Hi speediii,
I see several things that need to be cleaned up.
(1) You need to use FAIL_IF_QUIESCING on both the open and the get:
Code: |
openOptions = MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_INPUT_SHARED;
getOptions.options = MQC.MQGMO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING; |
(2) When client applications bang (poll) at a queue manager and then you stop the queue manager immediately then sometimes amqrmppa tasks hang around. You can simple kill them off.
i.e.
Code: |
ps -ef | grep <QMgrName> | grep mppa |grep -v grep | awk '{ print $2 }' | xargs -I {} kill -9 {} |
(3) What's with all of the logger code? The whole point of Log4J is to make your life EASIER. I would strongerly suggest that you read the manual for Log4J. But here is a Hello.java sample:
Code: |
import org.apache.log4j.Logger;
public class Hello
{
static Logger logger = Logger.getLogger(Hello.class);
public static void main(String argv[])
{
logger.debug("Hello world.");
logger.info("What a beatiful day.");
}
} |
Now in the "home" directory for the application create a file called: log4j.properties and put the following parameters in it:
Code: |
# root will control which appenders get the feed and at what level
log4j.rootCategory=DEBUG, LF, stdout
#
# stdout
#
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n
# "LF" appender writes to a file
log4j.appender.LF=org.apache.log4j.RollingFileAppender
# The name of the log file
log4j.appender.LF.File=hello.log
# Control the message level i.e. DEBUG or higher - INFO or higher, etc...
#log4j.appender.LF.Threshold=DEBUG
#log4j.appender.LF.Threshold=INFO
# Control the maximum log file size
log4j.appender.LF.MaxFileSize=100KB
# Archive log files (five backup files)
log4j.appender.LF.MaxBackupIndex=5
# Map out the layout of the log message
log4j.appender.LF.layout=org.apache.log4j.PatternLayout
log4j.appender.LF.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p (%F:%L) - %m%n |
Now by updating the "rootCategory", you can control where the logging feed goes to. Currently both the stdout and file-appender receive all messages above 'Debug' level. You can make each appender receive different message levels and if you look closely, you will see each appender formats the output slightly different.
Hope that helps.
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
speediii |
Posted: Wed Apr 26, 2006 2:29 am Post subject: |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
It was a good idea about the open options but it didn't help. I reduced my code so it just:
Code: |
while (true) {
try {
m_QMgr = new MQQueueManager(m_QMgrName);
} catch (Exception ex) {
log.error("Connect Error:", ex);
}
try {
m_QMgr.disconnect();
} catch (Exception ex) {
log.error("Disconnect Error:", ex);
}
wait(10);
} //End of while LOOP
|
And even this fails to release the MQ connection properly so I can restart the QM without it complaining, so it's nothing to do with the queue open options.
As for the Log4j stuff well I have a log4j.xml configuration and the useDefaultLogging() code is used if it fails to locate an xml configuration file so I can at least output an error and terminate.
Anyway, the only way round this I can see is that I need to terminate the application with an error code, ie. 2009 (MQRC_CONNECTION_BROKEN) and get the script to restart the app after a short wait.
This really shouldn't be happening?! |
|
Back to top |
|
 |
speediii |
Posted: Wed Apr 26, 2006 6:10 am Post subject: Problem SOLVED! |
|
|
Novice
Joined: 11 Apr 2006 Posts: 19
|
I noticed that the CSD was different from that of my dev machine & test environment.
I installed CSD07 on both. Problem solved.
Obviously this connection issue is a bug fixed by IBM. Thanks for all your support and am just happy to have gotten to the bottom of this.
Lee  |
|
Back to top |
|
 |
|