 | Level: Intermediate Willy Farrell (willyf@us.ibm.com), e-business Architect, IBM
01 Oct 2002 This article describes how to provide asynchronous messaging support for Enterprise JavaBeans applications, much like message-driven beans, which are not supported in WebSphere Application Server Version 4.x. Sample code is provided and discussed, and step-by-step instructions for deploying the code and configuring the application server are provided. All of the software used in this article is available for download.
Part 2 of this article will discuss performing JMS message processing and database access as part of the same unit of work using the transaction processing capability of WebSphere Application Server.
Introduction
Previously I wrote a two-part article explaining how to obtain, install, and configure tools from IBM for Java Message Service (JMS) development, namely WebSphere MQ and WebSphere Studio Application Developer (Application Developer). The articles had instructions and sample code that let you explore writing JMS programs for both the point-to-point (p2p) and publish and subscribe (pub/sub) domains. Instructions for configuring WebSphere MQ to use different transport mechanisms from the client to the server and for configuring remote queueing were also provided, with instructions on running the sample code within these configurations. The final section of the second article discussed using JMS within a Web application. I received many e-mails asking about topics I didn't cover in those articles. The two hottest topics had to do with WebSphere MQ within WebSphere Application Server (Application Server). Folks wanted to know:
- How can a process be set up within Application Server to monitor a queue and pass incoming messages to an Enterprise JavaBeans (EJB) component?
- How can JMS code within EJB components take advantage of the transaction processing capabilities of Application Server, especially in conjunction with database access?
This article addresses the first question, and a follow-up article will address the second. Instructions in this article do not assume you have carried out all the instructions in the previous two articles on WebSphere MQ and Application Developer, but also also do not assume a clean slate. I assume you have at least read the previous articles and have installed WebSphere MQ, the
WebSphere MQ classes for Java and JMS, and WebSphere Studio Application Developer (see
Resources for links to the software). I also assume those tools were installed in the directories specified in the previous articles; if not, adjust the instructions in this article accordingly. About versions
Some readers reported problems using different versions of the software than I used in the previous articles. Some had bought and installed a newer version of Application Developer than the trial version; a new version of the WebSphere MQ classes for Java and JMS was available after my
article; a new version of WebSphere MQ itself was released, and so on. In this age of
fast-moving technology growth, versions will always be a problem for these articles. I take painstaking care to ensure that all the
instructions will provide the results desired, if you use
the exact same versions of the software that I have. If you're using a different version
of any of the software referenced and you get an error, it probably
isn't your inability to follow directions. It's likely a version problem. Don't despair, and don't think I'm a total idiot for giving incorrect instructions; contact me because I, or somebody else, has most likely figured out a fix for your problem. Case in point: After my previous articles on WebSphere MQ were published, a newer version of the WebSphere MQ classes for Java and JMS were released that had an additional JAR file that was required in the classpath for JMS programs. Lack of this JAR file caused NoClassDefFoundError exceptions when following the instructions in the articles. There is a file available (see Resources) that explains the problem, describes the fix, and also provides updated configuration files for the newer version.
So, if you are using different versions of the software and are having a problem, contact me.
Installing sample code and configuration files
You should download and install the sample code and configuration files now. Later in the article, when each of the files is used, I'll give a detailed description of the file and its contents. First, download the code and copy the configuration files into the appropriate
WebSphere MQ folder:
- Download the sample code and configuration files. This file is named i-mqejb1.zip.
-
Extract the zip file to the C:\ folder on your system. Be sure to preserve
folder names when extracting. This will create a C:\MQEJB1 folder on your
system that contains the sample code and configuration files.
-
Copy C:\MQEJB1\JMSAdmin.fscontext.config to C:\WSMQ\Java\bin.
-
Copy C:\MQEJB1\setenv.bat to C:\WSMQ\Java\bin.
-
Copy C:\MQEJB1\setup.svc to C:\WSMQ\Java\bin.
Importing sample code into Application Developer
Next, import the sample code into Application Developer and create projects to hold the code.
- Launch Application Developer from the Start menu. From now on, the
instructions assume that Application Developer is running.
- Select File>Import... from the menu.
- Select EAR file and click Next.
- Type
C:\MQEJB1\mqejbs.ear in the
EAR file field.
- Type
MQEJBsEAR in the Enterprise application project name: field. Click Finish.
- You will see two warning messages in the Tasks view; you can safely
ignore these.
- Open a Java perspective.
- Right-click anywhere in the Packages view and select
New>Other....
- Select Java in the left pane, select Java Project in the right pane,
and click Next.
- Type
MQSamples in the Project name: field
and click Next.
- Click the Projects tab and check MQEJBs. This adds the MQEJBs project
to the build classpath for this project.
- Click the Libraries tab, then click Add External Jars....
- Navigate to C:\WSMQ\Java\lib, select com.ibm.mq.jar, com.ibm.mqjms.jar,
and connector.jar and click Open. These JAR files contain the WebSphere
MQ classes for Java and JMS that are used for this project.
-
Click Add External Jars..., then navigate to
C:\WSAD\plugins\com.ibm.etools.websphere.runtime\lib, select ivjejb35.jar,
j2ee.jar, runtime.jar, and websphere.jar, and click Open. ivjejb35.jar contains the classes for EJB Access Beans (more about those later), j2ee.jar contains the JMS interfaces, runtime.jar contains the ServerListener interface (more later), and websphere.jar contains
the CustomService interface (more later).
- Click Finish.
- Right-click on the MQSamples project and select New>Package....
- Type
com.ibm.ssya.mq.customservice in the Package: field and click Finish.
- Select the com.ibm.ssya.mq.customservice package.
- From the menu, select File>Import....
- Select File system and click Next.
- Set the directory to C:\MQEJB1.
- Select (do not check) MQEJB1 in the left pane, and check JMSCustomService.java
in the right pane. Click Finish.
 |
Simulating message-driven beans
EJB Version 2.0 introduced an enterprise bean called a message-driven bean (MDB). An MDB is a non-client bean that can respond to JMS messages arriving at a queue, providing an asynchronous notification mechanism for EJB applications. EJB Version 2.0 is part of Java 2 Enterprise Edition (J2EE) Version 1.3. WebSphere Application Server Advanced Edition Version 4.x does not support J2EE Version 1.3 (Application Server Version 5.x will); it provides support for J2EE Version 1.2,
and, therefore, EJB Version 1.1, which does not have MDBs. The question I often get is: "Until Application Server 5.x is released, is there some way to at least simulate MDBs in Application Server 4.x?" The answer involves setting up a listener for messages arriving at the queue, and then passing those messages to a stateless session bean for processing.
Ideally, the listener would be started and stopped with the application server where the session bean is deployed. And that's where it gets a little tricky. Application Server 4.x provides the com.ibm.websphere.runtime.CustomService interface, which can be implemented to "define a hook point to be executed at server startup and shutdown," to quote the documentation. But further reading of the documentation points out limitations to this interface, making it unsuitable for our purposes. The custom service class is called before the Java Naming and Directory Interface (JNDI) name server has been initialized, and no J2EE calls (such as calls to EJB components) are allowed. There is, however, another interface that can be used to provide the capabilities we're looking for. The com.ibm.ws.event.ServerListener interface,
in conjuction with the CustomService interface, lets you create a class that will receive event messages from the application server that signal the start or completion of certain steps in the server's lifecycle, such as startup, shutdown, and so on. By setting up the listener to the queue once the application server has finished its startup, we can provide the capability to simulate MDBs. The ServerListener interface is not documented, and, therefore, might not exist in future versions of Application Server (like Version 5.x). But that shouldn't faze you, because you'll get full support for MDBs in future versions of Application Server, and won't need to use ServerListener as a workaround.
The JMSCustomService class
The JMSCustomService class, provided in the sample code, is the class that receives incoming messages and passes them to an EJB component. Take a look at the different parts of that class, starting with the class declaration.
public class JMSCustomService
implements CustomService, ServerListener, MessageListener { |
JMSCustomService implements three interfaces:
CustomService
- So that it can be registered with the application server
ServerListener
- To receive event messages from the server
MessageListener
- So that it can receive asynchronous messages from JMS.
The CustomService interface requires two methods:
initialize() and shutdown().
initialize() is called early in the lifecycle of the
application server starting up, and, as its name implies, allows the object to
do any initialization required. shutdown() is called
when the server is -- you guessed it -- shutting down and allows the object to
do any cleanup required. Look at these methods in JMSCustomService.
public void initialize(Properties properties) throws Exception {
queueConnectionFactoryName =
properties.getProperty(QUEUE_CONNECTION_FACTORY);
queueName = properties.getProperty(QUEUE);
}
public void shutdown() throws Exception {
if (connection != null)
connection.close();
} |
The initialize() method is passed a
Properties object as a parameter. This object
has initialization values for the CustomService. In JMSCustomService, two properties are passed: the JNDI names of the QueueConnectionFactory and the Queue to be used for JMS processing. Later you'll see how the values are assigned to the properties. The shutdown() method in JMSCustomService merely closes the QueueConnection object, if one has been created. There are a number of methods required by the ServerListener interface, but the only one of interest here is the serverStarted() method. It is called by the application server once it has completed all startup processing. Below is the serverStarted() method for JMSCustomService.
public void serverStarted(ServerEvent event) {
try {
messageEJBFactory = new MessageEJBFactory();
Context context = new InitialContext();
QueueConnectionFactory factory =
(QueueConnectionFactory) context.lookup(queueConnectionFactoryName);
queue = (Queue) context.lookup(queueName);
connection = factory.createQueueConnection();
session =
connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
receiver = session.createReceiver(queue);
receiver.setMessageListener(this);
connection.start();
} catch (Throwable t) {
t.printStackTrace();
}
} |
The first line of serverStarted() creates an EJB factory for the stateless session bean, which simulates the MDB. An EJB factory is a JavaBeans component that provides simplified access to the home interface methods of an EJB component. EJB factories are provided as part of the Access Beans technology in Application Developer. The rest of this code is straightforward JMS processing:
- Look up the
QueueConnectionFactory and
Queue from JNDI
- Create a
QueueConnection
- Create a
QueueSession
- Create a
QueueReceiver
- Set the
QueueReceiver's MessageListener
- Then start the
QueueConnection to initiate message flow. At this point, messages received on the Queue will be passed to the onMessage() method of JMSCustomService, as shown below.
public void onMessage(Message message) {
try {
MessageEJB receiver = messageEJBFactory.create();
receiver.onMessage(message);
receiver.remove();
} catch (Throwable t) {
t.printStackTrace();
}
} |
First, a MessageEJB is created through the EJB factory instantiated in serverStarted(). MessageEJB is a stateless session bean that is being used to simulate an MDB. The onMessage() method of MessageEJB is called next, passing the message received here. Then the MessageEJB instance is removed. There is nothing very complicated about the code in JMSCustomService. Get the properties in initialize(), get the EJB factory and do standard setup for JMS processing in serverStarted(), and pass the message to the EJB component in onMessage().
The MessageEJB session bean
Now explore the code for MessageEJB by first looking at the
remote interface below.
public interface MessageEJB extends EJBObject, EJBMessageReceiver {
} |
A couple of things probably look strange here. First, there are no method signatures in the file. Second, you probably expected MessageEJB to extend the
MessageListener interface from JMS. These two things are related.
The MessageListener interface has one method, onMessage(), that receives a JMS Message as a parameter. However, the onMessage() method in MessageListener is not suitable for the remote interface of an EJB component because it does not throw a RemoteException, which is required for remote interface methods. To get around that, the sample code uses an interface written specifically to address the problem. EJBMessageReceiver, shown below, is an interface I wrote to provide an onMessage() method that could be used by the remote interface of an EJB component.
public interface EJBMessageReceiver {
public void onMessage(Message message)
throws JMSException, RemoteException;
} |
Use of this interface also explains why there are no method signatures in MessageEJB; the method signature for onMessage() is contained in the EJBMessageReceiver interface. Note the warning message on the onMessage() method in Application Developer indicating that the Message parameter must be Serializable. Message is not declared Serializable in the JMS API, but most vendor implementations of Message are serializable, including WebSphere MQ's, so we can safely ignore the warning. Now, look at the enterprise bean itself. There are two methods of interest in the MessageEJBBean class: onMessage() and ejbCreate(). In ejbCreate(), shown below, the local environment is used
to look up the JMS administered objects needed for JMS processing. These resource references are set in the deployment descriptor of the EJB component. You can open the MQEJBs project with the EJB Editor to see where these resource references are declared. Open the MQEJBs project with the EJB Extension Editor and you will see where the resource references are bound to actual JNDI names for the administered objects.
public void ejbCreate() throws CreateException {
try {
Context context = new InitialContext();
Context environment = (Context) context.lookup("java:comp/env");
factory =
(QueueConnectionFactory) environment.lookup(QUEUE_CONNECTION_FACTORY);
queue = (Queue) environment.lookup(QUEUE);
} catch (NamingException ne) {
throw new CreateException(ne.getMessage());
}
} |
As shown below, the onMessage() method in MessageEJBBean is called by JMSCustomService to pass the incoming message for processing.
public void onMessage(Message message) throws JMSException {
QueueConnection connection = factory.createQueueConnection();
QueueSession session =
connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
sender.send(
session.createTextMessage(((TextMessage) message).getText()));
connection.close();
} |
Here, the administered objects retrieved in ejbCreate() are used to do standard JMS setup, and the text of the message received is sent to another queue. This is just sample code, so sending the message to another queue provides a quick demonstration that the message has been received and processed, but the onMessage() method in a real application could do any kind of processing required.
Defining WebSphere MQ objects
Now that we've covered the JMSCustomService class
and MessageEJB component, you are ready to test them
in Application Developer (after some setup, of course). First, you need to define the WebSphere MQ objects that your application will access. You'll define a queue manager and queue for the incoming messages and a second queue manager and queue for the outgoing messages.
- Launch MQSeries Explorer from the Start menu. From now on, the instructions assume that MQSeries Explorer is running.
- Right-click on the Queue Managers folder and select New>Queue Manager.
- In the Queue Manager: field, type
QM1.
- In the Dead Letter Queue: field, type
SYSTEM.DEAD.LETTER.QUEUE (case is important).
- Click Next three times, then click Finish.
- Click the + sign next to Queue Managers.
- Click the + sign next to QM1.
- Right-click on the Queues folder and select New>Local Queue.
- In the Queue Name: field, type
Q1. Click OK.
- Right-click on the Queue Managers folder and select New>Queue Manager.
- In the Queue Manager: field, type
QM2.
- In the Dead Letter Queue: field, type
SYSTEM.DEAD.LETTER.QUEUE (case is important).
- Click Next three times.
- In the Listen on port number: field, type
1415, then click Finish.
- Click the + sign next to QM2.
- Right-click on the Queues folder and select New>Local Queue.
- In the Queue Name: field, type
Q2. Click OK.
Configuration files
Now you're ready to create the administered objects and bind them into the JNDI namespace. Take a look at the files you'll use to do that, starting with JMSAdmin.fscontext.config below.
#
# This is the default configuration file for the MQSeries Classes for
# Java Message Service Administration Tool.
#
# The following line specifies which JNDI service provider is in use.
# It currently indicates an LDAP service provider. If a different
# service provider is used, this line should be commented out and the
# appropriate one should be uncommented.
#
#INITIAL_CONTEXT_FACTORY=com.sun.jndi.ldap.LdapCtxFactory
INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory
#INITIAL_CONTEXT_FACTORY=com.ibm.ejs.ns.jndi.CNInitialContextFactory
#INITIAL_CONTEXT_FACTORY=com.ibm.websphere.naming.WsnInitialContextFactory
#
# The following line specifies the URL of the service provider's initial
# context. It currently refers to an LDAP root context. Examples of a
# file system URL and WebSphere's JNDI namespace are also shown,
# commented out.
#
#PROVIDER_URL=ldap://polaris/o=ibm,c=us
PROVIDER_URL=file:/C:/MQEJB1
#PROVIDER_URL=iiop://localhost/
#
# The following line specifies the security authentication model in use,
# and may be 'none' (for anonymous authentication), 'simple', or
# 'CRAM_MD5'.
#
SECURITY_AUTHENTICATION=none
#
# If you don't have SECURITY_AUTHENTICATION=none, then JMSAdmin will
# prompt you for the User DN and password. If you want to bypass these
# prompts then you can specify one or both of the values here. Since
# the password here is in cleartext this is not normally recommended
# except for testing. You should replace these values with your own.
#
#PROVIDER_USERDN=cn=Manager,o=ibm,c=uk
#PROVIDER_PASSWORD=secret
#
#
# The following line determines whether to use an InitialDirContext, or an
# InitialContext. Takes value of TRUE or FALSE.
#USE_INITIAL_DIR_CONTEXT=TRUE
#
# The following line specifies a prefix to add to names when carrying
# out operations such as lookup/bind.
#NAME_PREFIX=cn=
#
# The following line specifies a marker at which names will be truncated
# when viewing the contents of the Context.
#NAME_READABILITY_MARKER=..
#
# The three standard types of InitialContextFactory have the following
# defaults;
# Note that these defaults will be set automatically if the flags are
# not present, but will be overridden by including the flags.
#
# LDAP FSCONTEXT WEBSPHERE
# ------------------------------------------------------------------------------
# USE_INITIAL_DIR_CONTEXT TRUE FALSE FALSE
# NAME_PREFIX cn= omitted omitted
# NAME_READABILITY_MARKER omitted omitted ..
# |
This file will be used to set the configuration for the JMSAdmin program that is used to
create JMS administered objects and bind them into JNDI. For the sample code in this
article, you will use the file-based naming server provided with MA88 instead of the JNDI naming server provided by the WebSphere Test Environment in Application Developer. Because the WebSphere Test Environment does not retain the objects bound with JMSAdmin between invocations, it is necessary to use this naming server, which does not have that limitation.
Note that the binding information will be stored in the directory created when you extracted the sample code to your system. Now take a look at setenv.bat below.
@echo off
set MQ_JAVA_INSTALL_PATH=c:\wsmq\java
@rem Java runtime
set JAVA_HOME=C:\WSAD\plugins\com.ibm.etools.server.jdk\jre\bin
@rem MQ JMS
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib\com.ibm.mq.jar
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib\com.ibm.mqjms.jar
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib\jms.jar
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib\connector.jar
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib\fscontext.jar
set MQ=%MQ%;%MQ_JAVA_INSTALL_PATH%\lib\providerutil.jar
set CLASSPATH=%MQ%;%CLASSPATH%
set PATH=%JAVA_HOME%;%MQ_JAVA_INSTALL_PATH%\lib;%PATH%; |
setenv.bat sets the environment variables needed by JMSAdmin to function properly.
As you can see, it sets up JMSAdmin to use the WebSphere Test Environment Java Runtime Environment (JRE) and places all required .jar files in the classpath. The final configuration file to inspect is setup.svc.
def ctx(mq)
chg ctx(mq)
def qcf(MyQCF) qmgr(QM1)
def q(MyQueue) qmgr(QM1) queue(Q1)
def qcf(AnotherQCF) qmgr(QM2)
def q(AnotherQueue) qmgr(QM2) queue(Q2)
end |
This script creates the administered objects corresponding to the queue managers and
queues we created with MQSeries Explorer, placing them in the mq
context.
Creating the administered objects
Now, you can simply run the configuration commands, using the script file, to create the administered objects. Since you're not using the default JMSAdmin configuration file, you have to use the -cfg flag to indicate that JMSAdmin.fscontext.config contains the configuration information.
- Open a command prompt.
- Change directory to C:\WSMQ\Java\bin.
- Type
setenv and press Enter.
- Type
JMSAdmin<setup.svc -cfg JMSAdmin.fscontext.config and press Enter.
Defining a WebSphere test server
Next, you need to create and configure a server in Application Developer for the custom service and EJB component to run in.
- Open a Server perspective in Application Developer.
- Right-click on the Navigator view and select New>Server Project.
- Type
ServerProject in the Project name: field and click Finish.
- Right-click on ServerProject and select New>Server Instance and Configuration.
- In the Server name: field, type
TestServer.
- Select the Server instance type: as WebSphere 4.0 Test Environment.
- Click Finish.
- In the Server Configuration view, double-click TestServer under Server Configurations.
- Check Enable administration client.
- Change the Module visibility: field to
SERVER.
- Save the configuration by pressing Ctrl-S.
- In the Servers view, right click on TestServer and select Start.
- Wait until you see the message "Server Default Server open for e-business" before proceeding.
Configuring a JMS provider in the server
The next step is to use the server admin console to configure a JMS provider within
the application server. You'll configure the server to use WebSphere MQ as its
JMS provider, and then define the JMS ConnectionFactory and JMS Destination objects
accessed by the custom service and EJB component.
- In the Servers view, right-click on TestServer and select Run administrative client.
- At the Login screen, click Submit.
- Click the + sign next to Resources.
- Click JMS Providers.
- Click New.
- Ensure the Resource Provider Type: field is set to
IBM MQSeries (Local WebSphere Naming Context) and click Next.
- In the Server Class Path field, putting all of these entries on one line in the Server Class Path text field, type:
C:\WSMQ\Java\lib;
C:\WSMQ\Java\lib\com.ibm.mq.jar;
C:\WSMQ\Java\lib\com.ibm.mqjms.jar;
C:\WSMQ\Java\lib\connector.jar;
C:\WSMQ\Java\lib\fscontext.jar;
C:\WSMQ\Java\lib\providerutil.jar
This makes the WebSphere MQ Java classes available to the server.
- Change the Name: field to
WebSphere MQ.
- Change the Description: field to
WebSphere MQ using the file-based naming server.
- Change the External Initial Context Factory: field to
com.sun.jndi.fscontext.RefFSContextFactory.
- Change the External Provider URL: field to
file:/C:/MQEJB1.
- Click OK.
- Click the + sign next to JMS Providers.
- Click the + sign next to WebSphere MQ.
- Click JMS Destinations.
- Click New.
- In the Name: field, type
MyQueue.
- Change the JNDI Name: field to
jms/MyQueue.
- Set the Destination Type: field to
QUEUE.
- In the External JNDI Name: field, type
mq\MyQueue.
(Note the use of backslash "\" instead of slash "/". Because we are using the file-based naming server, we must use the operating system separator.)
- Click OK.
- Click New.
- In the Name: field, type
AnotherQueue.
- Change the JNDI Name: field to
jms/AnotherQueue.
- Set the Destination Type: field to
QUEUE.
- In the External JNDI Name: field, type
mq\AnotherQueue. (Note the backslash "\" instead of slash "/".)
- Click OK.
- Click JMS Connection Factories.
- Click New.
- In the Name: field, type
MyQCF.
- Change the JNDI Name: field to
jms/MyQCF.
- Change the External JNDI Name: field to
mq\MyQCF.
(Note the backslash "\" instead of slash "/".)
- Set the Connection Type: field to
QUEUE.
- Click OK.
- Click New.
- In the Name: field, type
AnotherQCF.
- Change the JNDI Name: field to
jms/AnotherQCF.
- Change the External JNDI Name: field to
mq\AnotherQCF. (Note the backslash "\" instead of slash "/".)
- Set the Connection Type: field to
QUEUE.
- Click OK.
 |
Configuring a custom service
Now we'll configure the application server to use the JMSCustomService class as a custom service.
- In the administration console, in the Web browser, click the + sign next to Nodes.
- Click the + sign next to localhost.
- Click the + sign next to Application Servers.
- Click the + sign next to Resources.
- Click the + sign next to Default Server.
- Click Custom Services.
- Click New.
- In the Display Name: field, type
JMS Custom Service.
- Check the Enable box.
- In the Classname: field, type
com.ibm.ssya.mq.customservice.JMSCustomService.
- In the Classpath: field, putting all of these entries on one line in the Classpath: text field, type:
C:\WSMQ\Java\lib;
C:\WSMQ\Java\lib\com.ibm.mq.jar;
C:\WSMQ\Java\lib\com.ibm.mqjms.jar;
C:\WSMQ\Java\lib\connector.jar;
C:\WSAD\workspace\MQSamples;
C:\MQEJB1\MessageEJB_classes.jar
This last JAR file contains the home and remote interfaces for MessageEJB,
and the EJB factory class for MessageEJB.
- Click OK.
- Click JMS Custom Service.
- Click Dynamic Properties.
- Click New.
- In the Name: field, type
queueConnectionFactory.
- In the Value: field, type
jms/MyQCF.
- Click OK.
- Click New.
- In the Name: field, type
queue.
- In the Value: field, type
jms/MyQueue.
- Click OK.
- Click OK again.
- Click OK once more.
- Click Save on the menu bar across the top of the Web browser.
- Click OK to save the configuration.
- Click Exit on the menu bar across the top of the Web browser.
- Close the Web browser by clicking the X next to Web browser.
- In the Servers view, right-click on TestServer and select Stop.
Note: With MessageEJB_classes.jar you only need the home and remote interface classes and the EJB factory class in the classpath of JMSCustomService for it to work. If you include other classes from the EJB component, in particular the generated classes, you will run into classloader problems and the remote calls to the EJB component won't work.
Testing the custom service
Now, you're finally ready to test the custom service. One last setup step, though -- you
need to assign the EJB component to run in the test server. Once you've done that, and
have started up the server, you can use MQSeries Explorer to put a test message on Q1 in
queue manager QM1. If everything is working correctly, you can then view the message on
Q2 of queue manager QM2.
- In the Server Configuration view, right-click on TestServer under Server Configurations, and select Add Project>MQEJBsEAR.
- In the Servers view, right-click on TestServer and select Start.
- Wait until you see the message "Server Default Server open for e-business" before proceeding.
- In MQSeries Explorer, right-click on Q1 and select Put Test Message...
- Type some text in the Message Data: field and click OK.
- Double-click on Q1 and you should see that the test message you just created is
no longer on the queue.
- Double-click on Q2 and you should see the test message is now on that queue.
- When you are done testing, make sure you stop TestServer.
Conclusion
It is fairly easy to provide asynchronous messaging capabilities to EJB applications in WebSphere Application Server 4.x. Other than the undocumented ServerListener interface, the code is very straightforward. I have tested this code in WebSphere Application Server Advanced Edition Version 4.0.3, and it works as it does in the WebSphere Test Environment of Application Developer, with these exceptions:
- I bound the JMS administered objects into the Application Server JNDI namespace, still in the
mq context.
- I used the IBM MQSeries JMS provider that is created by default when installing Application Server.
- I only defined the JMS Connection Factory
AnotherQCF under the IBM MQSeries JMS provider, and only defined the JMS Destination AnotherQueue under the IBM MQSeries JMS provider.
- I changed the value of the
queueConnectionFactory parameter for the custom service to mq/MyQCF; I changed the value of the queue parameter for the custom service to mq/MyQueue.
Stay tuned...
In the next article, I'll look at performing JMS message processing and database
access as part of the same unit of work using the transaction processing capability of
WebSphere Application Server.
Download | Name | Size | Download method |
|---|
| i-mqejb1.zip | | HTTP |
Resources
About the author  | 
|  |
Willy Farrell works for IBM Developer Relations Technical Consulting
(A.K.A. The DragonSlayers), providing education, enablement, and consulting to IBM business partners.
He has been programming computers for a living since 1981, began using Java in 1996, and joined IBM in 1998. Willy holds the following technical certifications, among others: Java 2 Programmer,
WebSphere Application Server Enterprise Developer, WebSphere Studio Application Developer Solution Developer, MQSeries Solutions Expert, and IBM e-business Solution Technologist. You can contact Willy at willyf@us.ibm.com. |
Rate this page
|  |