![]() |
![]() |
e-docs > WebLogic Server > Programming WebLogic Web Services > Creating JMS-Implemented WebLogic Web Services |
Programming WebLogic Web Services
|
Creating JMS-Implemented WebLogic Web Services
The following sections describe how to create JMS-implemented WebLogic Web services:
Overview of JMS-Implemented WebLogic Web Services
In addition to implementing a Web service operation with a stateless session EJB or a Java class, you can use a JMS message consumer or producer, such as a message-driven bean.
There are three types of JMS-implemented operations:
You implement this type of operation with a JMS message producer. The message producer publishes a message to the specified JMS topic, and a client invoking this message-style Web service component polls and receives the message.
Note: Receiving data from a JMS topic is deprecated in this version of WebLogic Server. This means that although this feature currently works, future versions of WebLogic Server might not support it.
If you are currently using this feature, update your application to use a stateless session EJB as the backend implementation of your Web service rather than a JMS topic. Program the EJB to use the JMS APIs to listen to the JMS topic in the same way that your client applications currently listen to the JMS implemented Web service. Then use the servicegen Ant task to reassemble your Web service. Finally, rewrite your client applications to poll the new EJB-implemented Web service for messages from the JMS topic.
When a client application sends data to a JMS-implemented Web service operation, WebLogic Server first converts the XML data to its Java representation using either the built-in or custom serializers, depending on whether the data type of the data is built-in or not. WebLogic Server then wraps the resulting Java object in a javax.jms.ObjectMessage object and puts it on the JMS destination. You can then write a JMS listener, such as a message-driven bean, to take the ObjectMessage and process it. Similar steps happen in reverse when a client application invokes a Web service to receive data from a JMS queue.
If you are using non-built-in data types, you must update the web-services.xml deployment descriptor file with the correct data type mapping information. If the Web service cannot find data type mapping information for the data, then it converts the data to a javax.xml.soap.SOAPElement data type, defined by the Java API for XML Messaging (JAXM).
Note: Input and return parameters to a Web service operation implemented with a JMS consumer or producer must implement the java.io.Serializable interface.
For detailed information about programming message-driven beans, see Programming WebLogic Enterprise JavaBeans.
Designing JMS-Implemented WebLogic Web Services
This section describes the relationship between JMS and WebLogic Web services operations implemented with a JMS consumer or producer, and design considerations for developing these types of Web services.
JMS queues implement a point-to-point messaging model whereby a message is delivered to exactly one recipient. JMS topics implement a publish/subscribe messaging model whereby a message is delivered to multiple recipients.
Before you implement a Web service operation with a JMS consumer or producer as the backend component, you must decide:
Retrieving and Processing Messages
After you decide what type of JMS destination you are going to use, you must decide what type of J2EE component will retrieve the message from the JMS destination and process it. Typically this will be a message-driven bean. This message-driven bean can do all the message-processing work, or it can parcel out some or all of the work to other EJBs. Once the message-driven bean finishes processing the message, the execution of the Web service is complete.
Because a single Web service operation cannot both send and receive data, you must create two Web service operations if you want a client application to be able to both send data and receive data. The sending Web service operation is related to the receiving one because the original message-driven bean that processed the message puts the response on the JMS destination corresponding to the receiving Web service operation.
Example of Using JMS Components
Figure 12-1 shows two separate Web service operations, one for receiving a message from a client and one for sending a message back to the client. The two Web service operations have their own JMS destinations. The message-driven bean gets messages from the first JMS destination, processes the information, then puts a message back onto the second JMS destination. The client invokes the first Web service operation to send the message to WebLogic Server and then invokes the second Web service operation to receive a message back from WebLogic Server.
Figure 12-1 Data Flow Between JMS-Implemented Web Service Operations and JMS
Implementing JMS-Implemented WebLogic Web Services
To implement a Web service implemented with a JMS message producer or consumer, follow these steps:
For detailed information, see Programming WebLogic Enterprise JavaBeans.
For more information on this step, see Configuring JMS Components for Message-Style Web Services.
Configuring JMS Components for Message-Style Web Services
This section assumes that you have already configured a JMS server. For information about configuring JMS servers, and general information about JMS, see the WebLogic Server Administration Guide and Programming WebLogic JMS.
To configure a JMS destination (either queue or topic) and JMS Connection Factory, follow these steps:
Assembling JMS-Implemented WebLogic Web Services Automatically
You can use the servicegen Ant task to automatically assemble a JMS-implemented Web service. The Ant task creates a web-services.xml deployment descriptor file based on the attributes of the build.xml file, optionally creates the non-built-in data type components (such as serialization class), optionally creates a client JAR file used to invoke the Web service, and packages everything into a deployable EAR file.
To automatically assemble a Web service using the servicegen Ant task:
For detailed information on this step, refer to Developing WebLogic Server Applications.
For details about specifying the servicegen Ant task, see Running the servicegen Ant Task.
For general information about creating Ant build files, see http://jakarta.apache.org/ant/manual/.
On Windows NT, execute the setWLSEnv.cmd command, located in the directory WL_HOME\server\bin, where WL_HOME is the top-level directory of your WebLogic Platform installation.
On UNIX, execute the setWLSEnv.sh command, located in the directory WL_HOME/server/bin, where WL_HOME is the top-level directory of your WebLogic Platform installation.
prompt> ant
Running the servicegen Ant Task
The following sample build.xml, files shows how to run the servicegen Ant task:
<project name="buildWebservice" default="ear">
<target name="ear">
<servicegen
destEar="jms_send_queue.ear"
contextURI="WebServices" >
<service
JMSDestination="jms.destination.queue1"
JMSAction="send"
JMSDestinationType="queue"
JMSConnectionFactory="jms.connectionFactory.queue"
JMSOperationName="sendName"
JMSMessageType="types.myType"
generateTypes="True"
targetNamespace="http://tempuri.org"
serviceName="jmsSendQueueService"
serviceURI="/jmsSendQueue"
expandMethods="True">
</service>
</servicegen>
</target>
</project>
In the example, the servicegen Ant task creates a single Web service called jmsSendQueueService. The URI to identify this Web service is /jmsSendQueue; the full URL to access the Web service is
http://host:port/WebServices/jmsSendQueue
The servicegen Ant task packages the Web service in an EAR file called jms_send_queue.ear. The EAR file contains a WAR file called web-services.war (default name) that contains all the Web service components, such as the web-services.xml deployment descriptor file.
The Web service exposes a single operation called sendName. Client applications that invoke this Web service operation send messages to a JMS queue whose JNDI name is jms.destination.queue1. The JMS ConnectionFactory used to create the connection to this queue is jms.connectionFactory.queue. The data type of the single parameter of the sendName operation is types.myType. Because the generateTypes attribute is set to True, the servicegen Ant task generates the non-built-in data type components for this data type, such as the serialization class.
Note: The types.myType Java class must be in servicegen's CLASSPATH so that servicegen can generate appropriate components.
Assembling JMS-Implemented WebLogic Web Services Manually
If you want to assemble a JMS-implemented WebLogic Web service manually, follow these steps:
The following sections describe JMS-specific information about assembling Web services manually.
Packaging the JMS Message Consumers and Producers
Package your JMS message consumers and producers (such as message-driven beans) into a JAR file.
When you create the EAR file that contains the entire Web service, put this JAR file in the top-level directory, in the same location as EJB JAR files.
Updating the web-services.xml File With Component Information
Use the <components> child element of the <web-service> element to list and describe the JMS backend components that implement the operations of the Web service. Each backend component has a name attribute that you later use when describing the operation that the component implements.
See Sample web-services.xml File for JMS Component Web Service for an example.
You can list the following types of backend components for JMS-implemented Web services:
This element describes a JMS backend component to which client applications send data. The component puts the sent data on to a JMS destination. Use the connection-factory attribute of this element to specify the JMS Connection factory that WebLogic Server uses to create a JMS Connection object. Use the <jndi-name> child element to specify the JNDI name of the destination, as shown in the following example:
<components>
<jms-send-destination name="inqueue"
connection-factory="myapp.myqueueCF">
<jndi-name path="myapp.myqueueIN" />
</jms-send-destination>
</components>
These elements describe two JMS backend components in which client applications receive data, the first from a JMS queue and the second from a JMS topic. Use the connection-factory attribute to specify the JMS Connection factory that WebLogic Server users to create a JMS Connection object. Use the <jndi-name> child element to specify the JNDI name of either the queue or the topic, as shown in the following example:
<components>
<jms-receive-queue name="outqueue"
connection-factory="myapp.myqueueCF">
<jndi-name path="myapp.myqueueOUT" />
</jms-receive-queue>
</components>
Sample web-services.xml File for JMS Component Web Service
The following sample web-services.xml file describes a Web service that is implemented with a JMS message consumer or producer:
<web-services>
<web-service targetNamespace="http://example.com"
name="myMessageService" uri="MessageService">
<components>
<jms-send-destination name="inqueue"
connection-factory="myapp.myqueuecf">
<jndi-name path="myapp.myinputqueue" />
</jms-send-destination>
<jms-receive-queue name="outqueue"
connection-factory="myapp.myqueuecf">
<jndi-name path="myapp.myoutputqueue" />
</jms-receive-queue>
</components>
<operations xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<operation invocation-style="one-way" name="enqueue"
component="inqueue" />
<params>
<param name="input_payload" style="in" type="xsd:anyType" />
</params>
</operation>
<operation invocation-style="request-response" name="dequeue"
component="outqueue" >
<params>
<return-param name="output_payload" type="xsd:anyType"/>
</params>
</operation>
</operations>
</web-service>
</web-services>
The example shows two JMS backend components, one called inqueue in which a client application sends data to a JMS destination, and one called outqueue in which a client application receives data from a JMS queue.
Two corresponding Web service operations, enqueue and dequeue, are implemented with these backend components.
The enqueue operation is implemented with the inqueue component. This operation is defined to be asynchronous one-way, which means that the client application, after sending the data to the JMS destination, does not receive a SOAP response (not even an exception.) The data sent by the client is contained in the input_payload parameter.
The dequeue operation is implemented with the outqueue component. The dequeue operation is defined as synchronous request-response because the client application invokes the operation to receive data from the JMS queue. The response data is contained in the output parameter output_payload.
Deploying JMS-Implemented WebLogic Web Services
Deploying a WebLogic Web service refers to making it available to remote clients. Because WebLogic Web services are packaged as standard J2EE Enterprise applications, deploying a Web service is the same as deploying an Enterprise application.
For detailed information on deploying Enterprise applications, see WebLogic Server Deployment.
Invoking JMS-Implemented WebLogic Web Services
This section shows two sample client applications that invoke JMS-implemented WebLogic Web services: one that sends data to a service operation, and one to receive data from another operation within the same Web service. The first operation is implemented with a JMS destination, the second with a JMS queue, as shown in the following web-services.xml file that describes the Web service:
<web-services xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<web-service
name="BounceService"
targetNamespace="http://www.foobar.com/echo"
uri="/BounceService">
<components>
<jms-send-destination name="inqueue"
connection-factory="weblogic.jms.ConnectionFactory">
<jndi-name path="weblogic.jms.inqueue" />
</jms-send-destination>
<jms-receive-queue name="outqueue"
connection-factory="weblogic.jms.ConnectionFactory">
<jndi-name path="weblogic.jms.outqueue" />
</jms-receive-queue>
</components>
<operations xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<operation invocation-style="one-way" name="submit" component="inqueue" >
</operation>
<operation invocation-style="request-response"
name="query" component="outqueue" >
<params>
<return-param name="output_payload" type="xsd:string"/>
</params>
</operation>
</operations>
</web-service>
</web-services>
Invoking an Asynchronous Web Service Operation to Send Data
The following example shows a dynamic client application that invokes the submit operation, described in the web-services.xml file in the preceding section. The submit operation sends data from the client application to the weblogic.jms.inqueue JMS destination. Because the operation is defined as one-way, it is asynchronous and does not return any value to the client application that invoked it.
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
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;
/**
* @author Copyright (c) 2002 by BEA Systems, Inc. All Rights Reserved.
*/
/**
* send2WS - this module sends to a specific Web service connected JMS queue
* If the message is 'quit' then the module exits.
*
* @returns
* @throws Exception
*/
public class send2WS{
public static void main( String[] args ) throws Exception {
// Setup the global JAX-RPC service factory
System.setProperty( "javax.xml.rpc.ServiceFactory",
"weblogic.webservice.core.rpc.ServiceFactoryImpl");
ServiceFactory factory = ServiceFactory.newInstance();
//define qnames
String targetNamespace = "http://www.foobar.com/echo";
QName serviceName = new QName( targetNamespace, "BounceService" );
QName portName = new QName( targetNamespace, "BounceServicePort" );
//create service
Service service = factory.createService( serviceName );
//create outbound call
Call Ws2JmsCall = service.createCall();
QName operationName = new QName( targetNamespace, "submit" );
//set port and operation name
Ws2JmsCall.setPortTypeName( portName );
Ws2JmsCall.setOperationName( operationName );
//add parameters
Ws2JmsCall.addParameter( "param",
new QName( "http://www.w3.org/2001/XMLSchema", "string" ), ParameterMode.IN
);
//set end point address
Ws2JmsCall.setTargetEndpointAddress(
"http://localhost:7001/BounceBean/BounceService" );
// get message from user
BufferedReader msgStream =
new BufferedReader(new InputStreamReader(System.in));
String line = null;
boolean quit = false;
while (!quit) {
System.out.print("Enter message (\"quit\" to quit): ");
line = msgStream.readLine();
if (line != null && line.trim().length() != 0) {
String result = (String)Ws2JmsCall.invoke( new Object[]{ line } );
if(line.equalsIgnoreCase("quit")) {
quit = true;
System.out.print("Done!");
}
}
}
}
}
Invoking a Synchronous Web Service Operation to Send Data
The following example shows a dynamic client application that invokes the query operation, described in the web-services.xml file in Invoking JMS-Implemented WebLogic Web Services. The client application invoking the query operation receives data from the weblogic.jms.outqueue JMS queue. Because the operation is defined as request-response, it is synchronous and returns the data from the JMS queue to the client application.
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;
/**
* @author Copyright (c) 2002 by BEA Systems, Inc. All Rights Reserved.
*/
/**
* fromWS - this module receives from a Web service associated JMS queue
* If the message is 'quit' then the module exits.
*
* @returns
* @throws Exception
*/
public class fromWS {
public static void main( String[] args ) throws Exception {
boolean quit = false;
// Setup the global JAX-RPC service factory
System.setProperty( "javax.xml.rpc.ServiceFactory",
"weblogic.webservice.core.rpc.ServiceFactoryImpl");
ServiceFactory factory = ServiceFactory.newInstance();
//define qnames
String targetNamespace = "http://www.foobar.com/echo";
QName serviceName = new QName( targetNamespace, "BounceService" );
QName portName = new QName( targetNamespace, "BounceServicePort" );
//create service
Service service = factory.createService( serviceName );
//create outbound call
Call Ws2JmsCall = service.createCall();
QName operationName = new QName( targetNamespace, "query" );
//set port and operation name
Ws2JmsCall.setPortTypeName( portName );
Ws2JmsCall.setOperationName( operationName );
//add parameters
Ws2JmsCall.addParameter( "output_payload",
new QName( "http://www.w3.org/2001/XMLSchema", "string" ),
ParameterMode.OUT );
//set end point address
Ws2JmsCall.setTargetEndpointAddress(
"http://localhost:7001/BounceBean/BounceService" );
System.out.println("Setup complete. Waiting for a message...");
while (!quit) {
String result = (String)Ws2JmsCall.invoke( new Object[] {} );
if(result != null) {
System.out.println("TextMessage:" + result);
if (result.equalsIgnoreCase("quit")) {
quit = true;
System.out.println("Done!");
}
continue;
}
try {Thread.sleep(2000);} catch (Exception ignore) {}
}
}
}
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |