 | Level: Advanced Babu Suresh (suresht@us.ibm.com), Advisory Software Engineer, IBM
29 Aug 2006 Learn how to design and develop an On Demand J2EE application using Publish and Subscribe MDBs, IBM Rational Application Developer, the Service Integration Bus, the Application Server Unit Test Engine, and IBM WebSphere Network Deployment. This detailed tutorial covers how to create MDBs to publish messages to other MDBs and explains how to directly deploy applications from the IDE into the application server network infrastructure.
Introduction
In this ever-growing, nonstop world of Java™, expectations and challenges are higher every day. Every one of us wants to stay on top of the continual changes, yet technical articles too often do not give the kinds of how-to details that a developer needs to know. Therefore, this tutorial shows you, in detailed steps, how to develop, deploy, and run an On Demand Java 2™ Platform Enterprise Edition™ (J2EE™) application. In the process, you will also learn how to do these related tasks:
- Use publish-and-subscribe (PubSub) messaging
- Create message driven beans (MDBs) to publish messages to other MDBs
- Use the IBM WebSphere® Enterprise Service Bus
- Develop Java™ Message Service (JMS) code in an IDE
- Promote the IBM WebSphere Application Server that comes with your IDE to the WebSphere Application Server network
- Deploy applications directly from the IDE into the WebSphere Application Server network
- Develop, deploy, and test the JMS application with the IDE only, without licensed messaging software
Scenario and design overview
At IBM, we have designed an application that is based on a real-life scenario, yet is easy to understand and relate to the technology. This design uses an application that exchanges information across different application servers in an on-demand fashion. Although there are many ways to write software, we chose messaging for this purpose, because it has the advantage of being both synchronous and asynchronous in nature.
In this practice scenario, a company that operates in different regions needs to fulfill customer orders for tangible goods. If a specific region cannot fill an order, it relies on other regions to fulfill them, instead. For security reasons, personnel in different regions cannot view each other's databases. Each region also has its own applications that run on its own application server and are visible only to staff in that particular region.
This exercise focuses on three regions, but you can apply this design to any number of regions. The beauty of this design is that all of the regions can use the same code base under different project names.
Design details
In the example that follows, three regions of the company share data through a common bus architecture in a WebSphere Application Server Network Deployment network infrastructure. Figure 1 uses different colors for each of the three destinations along the message route, as well as arrows that show the direction of the flow. For example, the Transfer Process bean from Region 1 sends the data to DESTINATION1, which forwards the request to the Check Inventory MDB in all regions.
The design that Figure 1 depicts makes these assumptions:
- Each region has different instances of the same code base.
- Each region has its own database.
- Each region has a unique Region ID, so that the MDB does not process the inventory fulfillment request message if the message comes from the same region.
Figure 1. Message flow diagram
If Region 1 wants to transfer an order to another region for fulfillment, it posts a Java Message Service message to the common bus destination, which is based on the Service Integration Bus technology and runs on the application server network. All of the MDBs that monitor the common bus destination are alerted, or triggered, through PubSub technology. Each MDB that is triggered responds by triggering the next MDB in the response chain. Messages use a standard language, such as XML. (You can use any format as the standard one, depending on your needs.)
For each of the functions, we have created a Topic, a Destination, and corresponding MDBs:
- A session bean called a TransferProcessBean that posts messages to DESTINATION1
- 3 PubSub MDBs that are triggered in this order:
-
CheckInventoryMDB, which monitors or listens to DESTINATION1 and posts to DESTINATION2
-
CompleteRRTransferMDB (where RR means Requesting Region), which listens to
DESTINATION2 and posts to DESTINATION3
-
CompleteARTransferMDB (where AR means Accepting Region), which listens to
DESTINATION3
In this example, the TransferProcessBean message uses the following format (your message format and content may be different, depending on your business):
Listing 1. Sample message format
<message>
<fromRegion>01</fromRegion>
<toRegion>ALL</toRegion>
<subject>TRANSFER-REQUEST</subject>
….add more tags as per your business needs
</message>
|
You can add more or different tags according to your business needs, of course.
As soon as the CheckInventoryMDB message is posted, every region that listens to DESTINATION1 gets triggered to respond. If a region has enough inventory to fulfill the customer's order, it automatically reserves the necessary items and sends a response that it has sufficient inventory to fulfill the order. That response goes to DESTINATION2, and the <toRegion> tag tells recipients in each region whether the message is meant for their region or not. The message looks basically like this:
Listing 2. Sample message format
<message>
<fromRegion>02</fromRegion>
<toRegion>01</toRegion>
<subject>TRANSFER-RESPONSE</subject>
<details>Fill in your info/data whether you can accept or not</details>
</message>
|
The CompleteRRTransferMDB instruction gets triggered in each region as soon as the previous message is posted in DESTINATION2. Only the MDB that is in the requesting region processes this message, because it is based on Region tag value. If there is more than one region that is able to fulfill the order, the requesting region's MDB chooses only one and sends a message on to DESTINATION3, accordingly.
Next, CompleteARTransferMDB, which listens to DESTINATION3, gets triggered. It completes the creation of the order in the new region, where the inventory exists, according to its order creation logic. Now the order transfer is complete.
Key advantages of this design
There are a few key considerations in this design:
- One single application can be developed and deployed in many different regions with minimal change.
- When you add a new region, it becomes part of the application server network and can exchange information with other regions with zero effort.
- Each region works independently, no matter what happens to other regions.
- No region needs to know how many other regions exist in the network.
- No region needs to know whether other regions are up and running.
- If a region is off-line, its messages will be delivered when it comes on-line again if it is configured properly, including properties like "durable" and others. Make sure not to confuse the term "region" as it has other meanings within the WebSphere environment on the zOS platform. Think "Region" as a "geography or geographies". Also make a note of one administrative domain i.e., a single WebSphere Application Server cell which makes this design work.
Hands-on training
Now that you understand the basic design, you can focus on how to use it within an IDE and an application server. For demonstration purposes, this example uses IBM Rational Application Developer® as the IDE and IBM WebSphere®Application Server Version 6.0 Unit Test Environment as the application server. After you have successfully tested in that environment, you will use use IBM WebSphere® Application Server Network Deployment V6.0 as the application server network, instead. The difference between the two is that the WebSphere Application Server Unit Test Environment can run only one application server, whereas WebSphere Application Server Network Deployment can run multiple application servers that support multiple regions. You should be able to achieve the same results in other IDEs and application servers that support similar technologies.
Create a session bean and MDBs
Start by creating a session bean and three MDBs.
To create the session bean:
- Open Rational Application Developer.
- Create a 2.1 Enterprise JavaBeans™ (EJB) project inside of a J2EE 1.4 application.
- In the EJB project, create a session bean called
TransferProcessBean. One
of the methods that you can use to do this, publishMessage1,
follows. It is coded to send a topic message. You may want to add your logic where you see writeYourLogicInThisMethod1.
Listing 3. Code for session bean
public void publishMessage1()
{
TopicConnectionFactory topicConnectionFactory = null;
TopicConnection topicConnection = null;
Topic topic = null;
TopicPublisher topicPublisher = null;
TopicSession topicSession = null;
String connectionFactoryName = "java:comp/env/TCF1IdeRef";
String topicName = "java:comp/env/Topic1IdeRef";
//Add your try, catch blocks
Context ctx = new InitialContext();
topicConnectionFactory = (TopicConnectionFactory) ctx
.lookup(connectionFactoryName);
topicConnection = topicConnectionFactory.createTopicConnection();
boolean transacted = false;
topicSession = topicConnection.createTopicSession(transacted,
TopicSession.AUTO_ACKNOWLEDGE);
topic = (Topic) ctx.lookup(topicName);
topicPublisher = topicSession.createPublisher(topic);
Message myOutgoingMessage1 = null;
//Add your logic in writeYourLogicInThisMethod1
String myOutgoingTmpMessage1 = writeYourLogicInThisMethod1();
myOutgoingMessage1 = topicSession.createTextMessage(myOutgoingTmpMessage1.trim());
//Publish the Topic
topicPublisher.publish(myOutgoingMessage1);
topicPublisher.close();
topicSession.close();
topicConnection.close();
}
|
Next, create the three MDBs:
- CheckInventoryMDB
- CompleteRRTransferMDB
- CompleteARTransferMDB
While you are creating each MDB, select:
- JMS type: javax.jms.MessageListener
- Transaction type: Container
- Activation configuration of destinationType: javax.jms.Topic
- Activation configuration of acknowledgeMode: Auto-acknowledge
The method that is activated when an MDB is triggered is onMessage. Add your logic for each of the MDBs in writeYourLogicInThisMethod2, according your needs. This is how the onMessage method looks:
Listing 4. The onMessage method
public void onMessage(javax.jms.Message msg)
{
String myIncomingMessage1;
//Add your try, catch blocks.
//Similar to Session Bean,
//make sure to declare JMS related stuffs and Close them once done
// Read the incoming Message
myIncomingMessage1 = ((TextMessage) msg).getText();
//Add your logic in writeYourLogicInThisMethod2
String myOutgoingMessage2 = writeYourLogicInThisMethod2 (myIncomingMessage1);
// Publish the Message. Code publishMessage2 similar to Session Bean
publishMessage2(myOutgoingMessage2);
} |
Configure JNDI references
The Java Naming and Directory Interface™ (JNDI) is part of the Java™ platform. It gives applications based on Java technology a unified interface to multiple naming and directory services. You will need to define several Activation Specifications, one for each MDB. These must be registered in JNDI, which you are ready to do now.
Edit your EJB DD (deployment descriptor), follow these steps:
- Under the Bean tab, select the CheckInventoryMDB.
- Under WebSphere Bindings, select the JCA Adapter.
- For ActivationSpec JNDI, enter
jms/AS1.
- For Destination JNDI name, enter
jms/Topic1.
- For CompleteRRTransferMDB, enter
jms/AS2
and jms/Topic2.
- For CompleteARTransferMDB, enter
jms/AS3
and jms/Topic3.
This means that when a message is posted in jms/Topic1, CheckInventoryMDB runs automatically. The same
happens for jms/Topic2 with CompleteRRTransferMDB and for jms/Topic3 with CompleteARTransferMDB.
Declare message destinations
Now you're ready to specify message destinations for the session bean and the MDBs.
For the session bean:
- In the EJB DD, go to the References tab and select the session bean.
- Add a new Resource Reference against Topic Connection Factory by typing the following entries:
-
Name:
TCF1IdeRef
-
Type:
javax.jms.TopicConnectionFactory
-
Auth:
Application
-
Share scope:
Shareable
-
Also add a new resource reference for the topic message by these entries:
-
Name:
Topic1IdeRef
-
Type:
javax.jms.Topic
-
Auth:
Application
-
Share scope:
Shareable
- Next, select Topic1IdeRef.
- Under WebSphere Bindings, update the JNDI name by typing
jms/Topic1.
- Similarly, enter
jms/TCF01 for TCF1IdeRef.
For the MDBs, replace or modify TCF1IdeRef and Topic1IdeRef with these entries:
- For CheckInventoryMDB:
TCF2IdeRef and Topic2IdeRef
- For CompleteRRTransferMDB:
TCF3IdeRef and Topic3IdeRef
Note: Remember that CompleteARTransferMDB does not post any messages; it simply listens to DESTINATION3. Therefore, you do not need to add references for that MDB.
Develop the front end
Now that you have built the application core, you need a mechanism to trigger the session bean that triggers other MDBs. There are many ways to trigger a session bean. For example, calling the session bean through a Java class, such as servlets or Faces JSP. Let us assume that you create a Faces JSP with a command button in it. Edit the Faces JSP, and then drag the session bean onto the command button, so that clicking the button triggers the session bean.
Define application server JMS parameters
You need JMS parameters inside the messaging engine that runs within the WebSphere Application Server Unit Test Engine. Rational Application Developer comes with a free copy. Here is what you must configure:
- Service integration bus
- Destinations
- Bus members
- Connection factories
- Activation specs
Note: To learn more, visit the WebSphere Application Server Version 6 Information Center (see the Resources section).
Start your WebSphere Application Server Unit Test Environment and go to the Admin Console. Do the following to enter the JMS parameters:
-
Step 1: Create a Service Integration Bus common bus
-
Under Service Integration, go to Buses
-
Create a new bus with the name
CommonBus1.
-
Step 2: Create bus destinations
-
Under Buses, go to CommonBus1/Destinations/New
-
Set Select destination type to Topic space.
-
Set Identifier as DESTINATION1.
-
Choose Bus member as your server.
-
Repeat Step 2 twice, once for DESTINATION2 and once for
DESTINATION3.
-
Step 3: Create Bus members
-
Under Service Integration, go to Buses.
-
Add a bus member for CommonBus1 by selecting
your node and server. ("Example:"
Node=pvtndserverNode01, Server=server1)
-
Step 4: Create Topic Connection Factories, Topics, and
Activation Specs:
Note: You will do Step 4 three times: 3 TCFs, 3 Topics and 3 ActivationSpecs. The values for second and third are within square brackets [ ]. For example: TCF1WASref [TCF2WASref, TCF3WASref].
- Under Resources> JMS Providers > Default messaging.
- Choose your node and server.
-
Step 4.1: Create the Topic Connection Factory.
-
JNDI name: jms/TCF01 [jms/TCF02 , jms/TCF03]
-
Bus name: CommonBus1
-
Client identifier value: (example) client1 [client2, client3]
-
Durability Subscription Home: Enter <
NodeName>.<serverName>-<busName> (Example: pvtndserverNode01.server1-CommonBus1)
-
Non-persistent message reliability: Assured persistent
-
Step 4.2: Create a topic for Topic1WASref [Topic2WASref,
Topic3WASref].
-
JNDI name:
jms/Topic1 [jms/Topic2,
jms/Topic3]
-
Topic Name:
Topic1IdeRef, which should be
the same value as your code for putting the message
into TopicName
[Topic2IdeRef, Topic3IdeRef]
-
Bus name:
CommonBus1
-
Topic space:
DESTINATION1 [DESTINATION2,
DESTINATION3]
-
Step 4.3: Create the activation spec.
Example:
AS1WASref [AS2WASref, AS3WASref].
-
JNDI name:
jms/AS1 [jms/AS2 , jms/AS3]
-
Destination type:
Topic
-
Destination JNDI name (matches the JNDI name
of your JMS Topic):
jms/Topic1 [jms/Topic2,
jms/Topic3]
-
Bus name:
CommonBus1
-
Subscription durability:
Durable
-
Subscription name: Example of value:
sn1 [sn2 ,
sn3]
-
Client identifier: The same name that you
entered for TCF/client identifier. Example:
client1 [client2, client3]
-
Durability Subscription Home: Enter the node name plus the server name plus the bus name. Example:
pvtndserverNode01.server1-CommonBus1
-
Step 5: Restart the WebSphere server.
-
Step 6: Deploy the application into the WebSphere Application Development Unit Test Environment and run the Faces JSP.
-
To deploy, right-click the WebSphere Application Server Unit Test Engine in
Servers view, and then choose the Add/Remove Projects submenu.
- Add your project.
- Select Finish.
-
To run the application, right-click the Faces JSP and choose the Run on Server submenu.
- Select your WebSphere Application Server Unit Test Engine configuration.
- Select Finish.
Your application is now ready to run and behave according to the coded logic. This completes the WebSphere Application Server Unit Test Engine level of testing.
Promote the WebSphere Application Server Unit Test Engine to the WebSphere Application Developer Network Deployment network
Your next step is to move from the WebSphere Application Server Unit Test Engine up to the WebSphere Application Server Network Deployment level, where you can achieve multiple regions.
Note: To do that, you need to have the WebSphere Application Server Network Deployment installed on a local or remote server.
- To promote the WebSphere Application Server Unit Test Engine to the WebSphere Application Server Network Deployment network, go to the command prompt of the WebSphere Application Server Unit Test Engine directory and run this command:
<RADinstall-root>\runtimes\base_v6\profiles\<profileName>\bin\addNode <WAS-ND hostname> -includeapps
- The flag
includeapps migrates all of your node-level applications and JMS parameters to ND automatically. It does not overwrite any cell-level information. Therefore, you need to do the steps 1 through 3 of the section "Define application server JMS parameters" from the WebSphere Application Server Network Deployment administration console.
- After issuing the
addNode command, you should get a message that confirms the success of your promotion from one level to the next.
- After that, to work in WebSphere Application Server Unit Test Environment you need to start one other Java Virtual Machine (JVM) process, called NodeAgent. To start NodeAgent, you must run this command:
<RADinstall-root>\runtimes\base_v6\profiles\<profileName>\bin\startNode
After you are finished with this exercise, you can restore the test environment to its previous state by running a removeNode command.
How to create a WebSphere Application Server Network Deployment server within Rational Application Developer
Now that you have promoted WebSphere Application Server Unit Test Environment to the WebSphere Application Server Network Deployment level, you need to be able to deploy the application directly from Rational Application Developer.
- Go to WebSphere Application Server Network Deployment administrator's console.
Typically, you can access it in your browser through <hostname >:9060/ibm/console. Confirm with your
WebSphere Application Server administrator that the port number is 9060.
- Make a note of the Deployment Manager name through ND-AdminConsole > System Administration > Deployment Manager > Name. Typically, it is dmgr.
- Also, make a note of the SOAP_CONNECTOR_ADDRESS port number through System Administration > Deployment Manager > Ports.
Return to your Rational Application Developer session.
- In Server view, create a new WebSphere Application Server V6.0 server with the host name pointing to the WebSphere Application Server Network Deployment machine.
-
In SOAP connecter port number, make sure to enter the
value, as noted previously.
-
For Server name, enter the Deployment Manager name, as previously noted.
-
For Server type, select Network Dep.
-
For Network Dep. server name, enter your cell name plus your node name plus your server name. Example:
pvtndserverCell01/sureshtWinASNode03/server1.
After you have created the application server, you can double-click that entry in the Servers view to see the configuration. It should look similar to the screen capture in Figure 2.
Figure 2. Sample of an application server configuration
Publish and run in WebSphere Application Server Network Deployment
Now you should be able to publish the application from Rational Application Developer into WebSphere Application Server Network Deployment, similar to the way did earlier in WebSphere Application Server Unit Test Environment. You should also be able to run the Faces JSP. In the results, make sure you see that MDBs are triggered and that then they trigger the next MDBs in line.
It will help to go back to Figure 1 and review the data flow:
-
TransferProcessBean session bean posts message
to DESTINATION1
-
CheckInventoryMDB listens to DESTINATION1 and
posts to DESTINATION2
-
CompleteRRTransferMDB listens to DESTINATION2
and posts to DESTINATION3
-
CompleteARTransferMDB listens to DESTINATION3
Your application is ready.
You may want to issue the removeNode command to release your WebSphere Application Server Unit Test Environment from the WebSphere Network Deployment network if you no longer need that setup. Be sure to see the WebSphere Application Server Version 6 Information Center for more information on the removeNode command.
This completes your exercise.
Conclusion
You have now developed and tested an On Demand J2EE application using the Service Integration Bus, PubSub MDBs, and both the Unit Test Environment and Network Deployment versions of the IBM WebSphere Application Server. Rational Application Developer migrates project artifacts from one version to the next, so you can and your team can benefit in the future, too, from the time and effort that it took for you to design, develop, and deploy the application.
Resources Learn
Get products and technologies
Discuss
About the author  | 
|  |
Babu Suresh is on the IBM Rational Quality Manager SVT team, which designs, develops and tests end-to-end user scenarios simulating real world situations. He has more than 18 years of experience in software design, development, maintenance, support, and test using various software and hardware platforms.
Author of the IBM developerWorks article titled Design, develop, and deploy an On Demand J2EE application. Co-author of the IBM internal white paper titled "WebSphere Application Server 4.0 problem determination guide." Speaker-Rational Software Developers Conference 2007, Orlando, FL. He holds an M.S in computer science and is also a veteran Toastmaster.
|
Rate this page
|  |