Hey guys,
I’m trying to get the webMethods Broker to act as a “normal” JMS provider, usable by a simple java application. Actually most things are already working, but I can not connect twice to the JMS provider via one Connection Factory.
I will explain you in what I did so far:
On MWS I created a provider, which is connected to one of my wM Brokers. The InitialContextFactory is “com.webMethods.jms.naming.WmJmsNamingCtxFactory”. In the next step I created a Connection Factory (no TopicConnectionFactory or QueueConnectionFactory), which refers to the provider I just created and the same wM Broker I used for the provider (“DemoConnectionFactory”). I have also set a Client ID (“DemoJmsClient”). I then created a Topic (“DemoTopic”). The last step on the MWS was to create an appropriate Document Type and add this Document Type to the correct Client Group.
My Java application consists of a simple class, which does the lookup and the sending/receiving task. Here is the corresponding source code:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
public class Client {
protected ConnectionFactory factory;
protected Destination destination;
protected Connection conn;
public boolean initialize(String factoryName, String destinationName) {
factory = lookupFactory(factoryName);
destination = lookupDestination(destinationName);
return factory != null && destination != null;
}
public boolean initialize(String factoryName) {
factory = lookupFactory(factoryName);
return factory != null;
}
private Destination lookupDestination(String name) {
try {
Context namingContext = new InitialContext();
Object destinationObject = namingContext.lookup(name);
namingContext.close();
if (destinationObject instanceof Destination) {
return (Destination) destinationObject;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private ConnectionFactory lookupFactory(String name) {
try {
Context namingContext = new InitialContext();
Object factoryObject = namingContext.lookup(name);
namingContext.close();
if (factoryObject instanceof ConnectionFactory) {
return (ConnectionFactory) factoryObject;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public boolean sendATextMessage(String message)
{
try {
if (conn == null) conn = factory.createConnection();
Session session = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer sender = session.createProducer(destination);
conn.start();
TextMessage msg = session.createTextMessage();
msg.setText(message);
sender.send(msg);
conn.stop();
return true;
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public String receiveATextMessage(Long timeout, Boolean printFullMessage)
{
try
{
if(conn == null) conn = factory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer receiver = session.createConsumer(destination);
conn.start();
TextMessage msg = (TextMessage)receiver.receive(timeout);
if(printFullMessage) System.out.println(msg.toString());
conn.stop();
return msg.getText();
}catch(Exception e)
{
e.printStackTrace();
}
return null;
}
}
This class is called by a simple method, which initializes the messaging, publishs a message to the topic and receives it again.
public class ClientTestSend {
/**
* @param args
*/
public static void main(String[] args) {
System.setProperty("java.naming.factory.initial", "com.webmethods.jms.naming.WmJmsNamingCtxFactory");
System.setProperty("java.naming.provider.url", "wmjmsnaming://ISBroker@10.104.34.16:6800");
// Initialize a new Client
Client myClient = new Client();
// Lookup ConnectionFactory and Destination (Topic or Queue)
if(myClient.initialize("DemoConnectionFactory", "DemoTopic")) System.out.println("Lookup successful!");
// Send a Textmessage to above chosen destination
if(myClient.sendATextMessage("Hello World to the Topic!")) System.out.println("Message sent!");
// Receive a Message from above chosen destination
System.out.println(myClient.receiveATextMessage(30000L, false));
}
}
If I run this method, everything is okay, the message is sent and received. However the problem occures, if I run two instances of the application, where the first one just has the receive method and waits for 30 seconds and the other one has to send the message. As soon as if I try to connect with the second instance, I get the following exception:
javax.jms.InvalidClientIDException: [BRM.10.2002] JMS: Client ID "DemoJmsClient" is already in use.
The wM documentation says,
If a client ID is specified, the connection factory derives a
client ID from this value each time a connection is
established.
([URL]http://techcommunity.softwareag.com/ecosystem/documentation/webmethods/wmsuites/wmsuite8-2_sp2/Broker_and_JMS/8-2-SP2_Administering_Broker.pdf[/URL] on page 431). However if my receive application is waiting for a message, it is listed as “DemoJmsClient (JMS##Connection)” in the Clients list on MWS. There is no derived name from the specified one.
So the question is: What am I doing wrong? I can’t imagine, that I can just produce one Client from a Connection Factory.
Thanks in advance and best regards,
Stefan