There are a variety of models for messaging in a distributed computing environment. The fundamental concept behind these models differs in the degree to which the two systems are synchronized. At one end, it is the synchronous model in which a system sends a message and waits for response. At the other end, it is the asynchronous model in which a system sends the message and continues processing (Fire-and-forget message exchange). Sending a message does not always require both systems to be up and ready at the same time. Participants in an asynchronous messaging system don't have to wait for a response from the recipient, because they can rely on the messaging infrastructure to ensure delivery. Asynchronous messaging is the strategy of choice for loosely coupled, Service-Oriented Architecture (SOA) because it overcomes the inherent limitations of remote communication, such as latency and unreliability.
The core of asynchronous messaging is Message-oriented middleware (MOM) like IBM MQSeries®. Let's look at how this works: To send a message, System A puts the message in the MOM using APIs exposed by MOM. System B, which wants to receive the message, can get the message from MOM using APIs exposed by MOM. If you don't have MOM libraries to use MOM APIs at your end, we can use a generic Web service, which exposes a method to put messages in MOM. The system which wants to send messages will need a Web service client. This client will be invoked when the system wants to send a message, and it will invoke the Web service and a message will be put into the MOM by the Web service.
Configure WebSphere Application Server Version 6 for default messaging
To demonstrate the concept for this article, we need to configure WebSphere Application Server, version 6 (here after called WAS). To configure the WAS, perform the following steps:
- Create a bus
- Create a bus member
- Create a Destination
- Create a JMS connection factory
- Create a JMS queue
- Create a JMS activation specification
For detailed information on how to follow these steps, refer to the article "Deploying message-driven beans and JMS applications into the Service Integration Bus" in the Resources section.
Using Web services to put messages into MOM
The Web service will have a method which, when invoked, will put a message into a queue. For the purpose of demonstration, we’ll use a text message, although the Web service can be written for any JMS message type. For information on how to write Java Web services, refer to the Redbook "WebSphere version 6 Web Services Handbook Development and Deployment", which is noted in the Resources section. Listing 1 shows the putMessage method of a sample Web service used for testing the code for this article.
Listing 1. putMessage method
public void putMessage(String message){
try {
Properties prop = new Properties();
prop.put(InitialContext.INITIAL_CONTEXT_FACTORY,
"com.ibm.websphere.naming.WsnInitialContextFactory");
prop.put(InitialContext.PROVIDER_URL,
"corbaloc:iiop:localhost:2809");
InitialContext context = new InitialContext(prop);
//Do the lookup for Queue connection factory.
QueueConnectionFactory
factory =(QueueConnectionFactory)context.lookup("JMS/MyQueue_CF");
//Do the lookup for Queue.
Destination queue = (Destination) context.lookup("JMS/queue");
//Create connection and start it.
Connection connection = factory.createConnection();
connection.start();
System.out.println("connection created");
//Create session and message producer.
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer producer=session.createProducer(queue);
System.out.println("producer created");
System.out.println(producer.getDestination().toString());
//Prepare the text message.
TextMessage msg=session.createTextMessage();
msg.setText(message);
//Send the message.
producer.send( msg);
System.out.println("sent message : "+msg.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
|
The putMessage method looks for a Connection Factory, JMS Destination objects into JNDI. Then it creates the connection, session and finally a message producer for the JMS destination, puts the text message into the queue.
The database configuration is required to automatically invoke the Web service client. This can be done in a number of ways. For example, you could write a Trigger and Trigger calling User Defined Function, or write a Trigger and Trigger calling a Java Stored Procedure. For the purpose of demonstration we use Trigger and Java Stored Procedure combination and DB2 database. Perform the following steps to configure your database.
Run the following SQL command to create a table:
Listing 2. SQL for sample table creation
CREATE TABLE customer
(
pkey INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START
WITH 1, INCREMENT BY 1, NO CACHE ) PRIMARY KEY,
fname VARCHAR(20),
lname VARCHAR(20),
ccode VARCHAR(10)
);
|
This Java Stored Procedure (Java SP) is the key behind the concept of this article. The Java class which will be invoked when this Java SP is called, will have code to invoke the Web service. Run the following SQL command to create a Java SP.
Listing 3. SQL for Java SP creation
CREATE PROCEDURE MyPROCEDURE ( IN var0 INTEGER,IN var1 VARCHAR(20) )
SPECIFIC SQL060622110835012
DYNAMIC RESULT SETS 1
NOT DETERMINISTIC
LANGUAGE Java
EXTERNAL NAME 'MyPROCEDURE.invokeWS'
FENCED
THREADSAFE
PARAMETER STYLE JAVA
|
The below code listing shows the MyPROCEDURE Java class. This class has a method called invokeWS. This method takes three parameters, the primary key, the action performed on the table (create, update, delete) and a result set. I have used Axis APIs to write the Web service client code in this method. For compiling and running this class, make sure Axis jars are in your class path.
Listing 4. Java class for Java SP
import java.sql.*;
import java.io.FileOutputStream;
import java.io.PrintStream;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.Service;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;
public class MyPROCEDURE
{
public static void invokeWS ( int var0, String var1, ResultSet[] rs1 )
throws SQLException, Exception
{
try{
//create service factory
ServiceFactory factory = ServiceFactory.newInstance();
// define qnames
String targetNamespace = "http://asyncmessage.ibm.com";
QName serviceName = new QName(targetNamespace,"AsynchronousMessageWSService");
QName portName = new QName(targetNamespace,"AsynchronousMessageWS");
QName operationName = new QName(targetNamespace,"putMessage");
// create service
Service service = factory.createService(serviceName);
// create call
Call call = service.createCall();
// set port and operation name
call.setPortTypeName(portName);
call.setOperationName(operationName);
// add parameters
call.addParameter("message",
new QName(targetNamespace,"string"),ParameterMode.IN);
call.setReturnType(new QName("",""));
// set end point address
call.setTargetEndpointAddress("http://localhost:9080/AsyncMessagingSamples
/service/AsynchronousMessageWS");
// invoke the remote web service
call.invoke(new Object[]
{ "Message from DB2 : a row with primary key"+var0+" is "+var1+"d"});
}catch(Exception e)
{
try{
FileOutputStream fout=new FileOutputStream("errors.txt");
e.printStackTrace(new PrintStream(fout));
}catch(Exception e1){}
}
}
}
|
Create Triggers on the sample table
In the sample code, we have created three Triggers on the customer table for Insert, Update, and Delete. This is used, for example, whenever a row is inserted, updated or deleted in the customer table. When one of these things occurs, Triggers will be executed. These Triggers will then call the Java SP, which in turns invoke the invokeWS method. Run the following SQL command to create Triggers. Let’s see how this works:
Listing 5. SQL to create Triggers on Sample Table
//Trigger for row insertion
CREATE TRIGGER event_create
AFTER INSERT ON CUSTOMER REFERENCING NEW AS N
FOR EACH ROW MODE DB2SQL
call MYPROCEDURE(N.pkey,'create') ;
//Trigger for row updation
REATE TRIGGER event_udpate
AFTER UPDATE ON CUSTOMER REFERENCING NEW AS N
FOR EACH ROW MODE DB2SQL
call MYPROCEDURE(N.pkey,'update') ;
//Trigger for row deletion
CREATE TRIGGER event_delete
AFTER DELETE ON CUSTOMER REFERENCING OLD AS O
FOR EACH ROW MODE DB2SQL
call MYPROCEDURE(N.pkey,'delete') ;
|
To complete the scenario, we need to create a Message Driven Bean (MDB). This MDB will subscribe to the Queue, in which our Web service will put the messages. For detailed information on how to configure the MDB, refer to the article "Deploying message-driven beans and JMS applications into the Service Integration Bus", which you can find in the Resources section. Listing 6 shows snippets from ibm-ejb-jar-bnd.xmi file and the onMessage method of sample MDB used for this article.
Note: some parts of ibm-ejb-jar-bnd.xmi file have been truncated for easy reading and important attributes have been marked bold.
Listing 6. snippets from onMessage and ibm-ejb-jar-bnd.xmi file.
.........................................................
<ejbBindings .....
activationSpecJndiName="eis/MyQueue_activation_spec" destinationJndiName="JMS/queue">
..........................................................
<resRefBindings ......... jndiName="JMS/MyQueue_CF">
..........................................................
<resRefBindings ..... jndiName="JMS/queue">
...........................................................
</ejbBindings>
public void onMessage (javax.jms.Message msg)
{
try {
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***"+((TextMessage)msg).getText()+"***");
System.out.println("***********************************");
System.out.println("***********************************");
} catch (JMSException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
|
We've completed the required setup. Deploy the web service in WebSphere Application Server. Now whenever we create, update or delete a row in a customer table, a message will be written in SystemOut.log file of WebSphere Application Serverby MDB. If you create a row with primary key 100 in a customer table, the message will look like "Message from DB2: a row with primary key 100 is created".
In this article, we learned how we can enable asynchronous messaging over HTTP using Web services. The major benefit of this approach is that this is platform and language independent and it gives you freedom from writing JMS clients to send messages to MOM.
The author would like to thank Krishnakumar Balachandar (KK), WebSphere Community Edition/Geronimo L3 Support Lead, Shishir Narain, WebSphere Partner Gateway development, and Shaji Vaidyan, WebSphere Adapter for JDBC, Support and Development for their reviews and comments on this article.
| Description | Name | Size | Download method |
|---|---|---|---|
| Code samples for this article | samples.zip | 10KB | HTTP |
Information about download methods
- "Deploying message-driven beans and JMS applications into the Service Integration Bus" (developerWorks, April 2005) shows how WebSphere Application Server V6 makes it easy to build message buses and deploy applications, and how IBM Rational®Application Developer enables developers to create and test JMS applications that communicate using the message bus.
- "Solve common problems with DB2 UDB Java stored procedures" (developerWorks, October 2005) shows working examples and common solutions to help you get up and running, problem free, with your own Java routines.
- The IBM Rebook "WebSphere Version 6 Web Services Handbook Development and Deployment" describes the concepts of Web services from various perspectives.
Comments (Undergoing maintenance)





