Wednesday Dec 05, 2012

JMS Step 5 - How to Create an 11g BPEL Process Which Reads a Message Based on an XML Schema from a JMS Queue

JMS Step 5 - How to Create an 11g BPEL Process Which Reads a Message Based on an XML Schema from a JMS Queue

Welcome to another post in the series of blogs which demonstrates how to use JMS queues in a SOA context. The previous posts were:

  1. JMS Step 1 - How to Create a Simple JMS Queue in Weblogic Server 11g
  2. JMS Step 2 - Using the QueueSend.java Sample Program to Send a Message to a JMS Queue
  3. JMS Step 3 - Using the QueueReceive.java Sample Program to Read a Message from a JMS Queue
  4. JMS Step 4 - How to Create an 11g BPEL Process Which Writes a Message Based on an XML Schema to a JMS Queue

Today we will create a BPEL process which will read (dequeue) the message from the JMS queue, which we enqueued in the last example. The JMS adapter will dequeue the full XML payload from the queue.

1. Recap and Prerequisites

In the previous examples, we created a JMS Queue, a Connection Factory and a Connection Pool in the WebLogic Server Console. Then we designed and deployed a BPEL composite, which took a simple XML payload and enqueued it to the JMS queue. In this example, we will read that same message from the queue, using a JMS adapter and a BPEL process. As many of the configuration steps required to read from that queue were done in the previous samples, this one will concentrate on the new steps. A summary of the required objects is listed below. To find out how to create them please see the previous samples. They also include instructions on how to verify the objects are set up correctly.

WebLogic Server Objects

Object Name

Type

JNDI Name

TestConnectionFactory

Connection Factory

jms/TestConnectionFactory

TestJMSQueue

JMS Queue

jms/TestJMSQueue

eis/wls/TestQueue

Connection Pool

eis/wls/TestQueue

Schema XSD File

The following XSD file is used for the message format. It was created in the previous example and will be copied to the new process.

stringPayload.xsd

<?xml version="1.0" encoding="windows-1252" ?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"

                xmlns="http://www.example.org"

                targetNamespace="http://www.example.org"

                elementFormDefault="qualified">

  <xsd:element name="exampleElement" type="xsd:string">

  </xsd:element>

</xsd:schema>

JMS Message

After executing the previous samples, the following XML message should be in the JMS queue located at jms/TestJMSQueue:

<?xml version="1.0" encoding="UTF-8" ?><exampleElement xmlns="http://www.example.org">Test Message</exampleElement>

JDeveloper Connection

You will need a valid Application Server Connection in JDeveloper pointing to the SOA server which the process will be deployed to.

2. Create a BPEL Composite with a JMS Adapter Partner Link

In the previous example, we created a composite in JDeveloper called JmsAdapterWriteSchema. In this one, we will create a new composite called JmsAdapterReadSchema.

There are probably many ways of incorporating a JMS adapter into a SOA composite for incoming messages. One way is design the process in such a way that the adapter polls for new messages and when it dequeues one, initiates a SOA or BPEL instance. This is possibly the most common use case. Other use cases include mid-flow adapters, which are activated from within the BPEL process. In this example we will use a polling adapter, because it is the most simple to set up and demonstrate. But it has one disadvantage as a demonstrative model. When a polling adapter is active, it will dequeue all messages as soon as they reach the queue. This makes it difficult to monitor messages we are writing to the queue, because they will disappear from the queue as soon as they have been enqueued. To work around this, we will shut down the composite after deploying it and restart it as required. (Another solution for this would be to pause the consumption for the queue and resume consumption again if needed. This can be done in the WLS console JMS-Modules -> queue -> Control -> Consumption -> Pause/Resume.)

We will model the composite as a one-way incoming process. Usually, a BPEL process will do something useful with the message after receiving it, such as passing it to a database or file adapter, a human workflow or external web service. But we only want to demonstrate how to dequeue a JMS message using BPEL and a JMS adapter, so we won’t complicate the design with further activities. However, we do want to be able to verify that we have read the message correctly, so the BPEL process will include a small piece of embedded java code, which will print the message to standard output, so we can view it in the SOA server’s log file. Alternatively, you can view the instance in the Enterprise Manager and verify the message.

The following steps are all executed in JDeveloper. Create the project in the same JDeveloper application used for the previous examples or create a new one.

Create a SOA Project

Create a new project and choose SOA Tier > SOA Project as its type. Name it JmsAdapterReadSchema. When prompted for the composite type, choose Empty Composite.

Create a JMS Adapter Partner Link

In the composite editor, drag a JMS adapter over from the Component Palette to the left-hand swim lane, under Exposed Services.

This will start the JMS Adapter Configuration Wizard. Use the following entries:

Service Name: JmsAdapterRead

Oracle Enterprise Messaging Service (OEMS): Oracle WebLogic JMS

AppServer Connection: Use an application server connection pointing to the WebLogic server on which the JMS queue and connection factory mentioned under Prerequisites above are located.

Adapter Interface > Interface: Define from operation and schema (specified later)

Operation Type: Consume Message
Operation Name:
Consume_message

Consume Operation Parameters

Destination Name: Press the Browse button, select Destination Type: Queues, then press Search. Wait for the list to populate, then select the entry for TestJMSQueue , which is the queue created in a previous example.

JNDI Name: The JNDI name to use for the JMS connection. As in the previous example, this is probably the most common source of error. This is the JNDI name of the JMS adapter’s connection pool created in the WebLogic Server and which points to the connection factory. JDeveloper does not verify the value entered here. If you enter a wrong value, the JMS adapter won’t find the queue and you will get an error message at runtime, which is very difficult to trace. In our example, this is the value eis/wls/TestQueue . (See the earlier step on how to create a JMS Adapter Connection Pool in WebLogic Server for details.)


Messages/Message Schema
URL:
We will use the XSD file created during the previous example, in the JmsAdapterWriteSchema project to define the format for the incoming message payload and, at the same time, demonstrate how to import an existing XSD file into a JDeveloper project.

Press the magnifying glass icon to search for schema files. In the Type Chooser, press the Import Schema File button.


Select the magnifying glass next to URL to search for schema files. Navigate to the location of the JmsAdapterWriteSchema project > xsd and select the stringPayload.xsd file.

Check the “Copy to Project” checkbox, press OK and confirm the following Localize Files popup.

Now that the XSD file has been copied to the local project, it can be selected from the project’s schema files. Expand Project Schema Files > stringPayload.xsd and select exampleElement: string .

Press Next and Finish, which will complete the JMS Adapter configuration.
Save the project.

Create a BPEL Component

Drag a BPEL Process from the Component Palette (Service Components) to the Components section of the composite designer. Name it JmsAdapterReadSchema and select Template: Define Service Later and press OK.

Wire the JMS Adapter to the BPEL Component

Now wire the JMS adapter to the BPEL process, by dragging the arrow from the adapter to the BPEL process. A Transaction Properties popup will be displayed. Set the delivery mode to async.persist.

This completes the steps at the composite level.

3 . Complete the BPEL Process Design

Invoke the BPEL Flow via the JMS Adapter

Open the BPEL component by double-clicking it in the design view of the composite.xml, or open it from the project navigator by selecting the JmsAdapterReadSchema.bpel file. This will display the BPEL process in the design view. You should see the JmsAdapterRead partner link in the left-hand swim lane.

Drag a Receive activity onto the BPEL flow diagram, then drag a wire (left-hand yellow arrow) from it to the JMS adapter. This will open the Receive activity editor. Auto-generate the variable by pressing the green “+” button and check the “Create Instance” checkbox. This will result in a BPEL instance being created when a new JMS message is received.

At this point it would actually be OK to compile and deploy the composite and it would pick up any messages from the JMS queue. In fact, you can do that to test it, if you like. But it is very rudimentary and would not be doing anything useful with the message. Also, you could only verify the actual message payload by looking at the instance’s flow in the Enterprise Manager.

There are various other possibilities; we could pass the message to another web service, write it to a file using a file adapter or to a database via a database adapter etc. But these will all introduce unnecessary complications to our sample. So, to keep it simple, we will add a small piece of Java code to the BPEL process which will write the payload to standard output. This will be written to the server’s log file, which will be easy to monitor.

Add a Java Embedding Activity

First get the full name of the process’s input variable, as this will be needed for the Java code. Go to the Structure pane and expand Variables > Process > Variables. Then expand the input variable, for example, "Receive1_Consume_Message_InputVariable > body > ns2:exampleElement”, and note variable’s name and path, if they are different from this one.

Drag a Java Embedding activity from the Component Palette (Oracle Extensions) to the BPEL flow, after the Receive activity, then open it to edit.


Delete the example code and replace it with the following, replacing the variable parts with those in your sample, if necessary.:

System.out.println("JmsAdapterReadSchema process picked up a message");

oracle.xml.parser.v2.XMLElement inputPayload =  

 (oracle.xml.parser.v2.XMLElement)getVariableData(

                          "Receive1_Consume_Message_InputVariable",

                          "body",

                          "/ns2:exampleElement");  

String inputString = inputPayload.getFirstChild().getNodeValue();

System.out.println("Input String is " + inputPayload.getFirstChild().getNodeValue());

Tip. If you are not sure of the exact syntax of the input variable, create an Assign activity in the BPEL process and copy the variable to another, temporary one. Then check the syntax created by the BPEL designer.

This completes the BPEL process design in JDeveloper. Save, compile and deploy the process to the SOA server.

3. Test the Composite

Shut Down the JmsAdapterReadSchema Composite

After deploying the JmsAdapterReadSchema composite to the SOA server it is automatically activated. If there are already any messages in the queue, the adapter will begin polling them. To ease the testing process, we will deactivate the process first

Log in to the Enterprise Manager (Fusion Middleware Control) and navigate to SOA > soa-infra (soa_server1) > default (or wherever you deployed your composite to) and click on JmsAdapterReadSchema [1.0] . Press the Shut Down button to disable the composite and confirm the following popup.

Monitor Messages in the JMS Queue

In a separate browser window, log in to the WebLogic Server Console and navigate to Services > Messaging > JMS Modules > TestJMSModule > TestJMSQueue > Monitoring. This is the location of the JMS queue we created in an earlier sample (see the prerequisites section of this sample). Check whether there are any messages already in the queue. If so, you can dequeue them using the QueueReceive Java program created in an earlier sample. This will ensure that the queue is empty and doesn’t contain any messages in the wrong format, which would cause the JmsAdapterReadSchema to fail.

Send a Test Message

In the Enterprise Manager, navigate to the JmsAdapterWriteSchema created earlier, press Test and send a test message, for example “Message from JmsAdapterWriteSchema”.

Confirm that the message was written correctly to the queue by verifying it via the queue monitor in the WLS Console.

Monitor the SOA Server’s Output

A program deployed on the SOA server will write its standard output to the terminal window in which the server was started, unless this has been redirected to somewhere else, for example to a file. If it has not been redirected, go to the terminal session in which the server was started, otherwise open and monitor the file to which it was redirected.

Re-Enable the JmsAdapterReadSchema Composite

In the Enterprise Manager, navigate to the JmsAdapterReadSchema composite again and press Start Up to re-enable it. This should cause the JMS adapter to dequeue the test message and the following output should be written to the server’s standard output:

JmsAdapterReadSchema process picked up a message.

Input String is Message from JmsAdapterWriteSchema

Note that you can also monitor the payload received by the process, by navigating to the the JmsAdapterReadSchema’s Instances tab in the Enterprise Manager. Then select the latest instance and view the flow of the BPEL component. The Receive activity will contain and display the dequeued message too.

4 . Troubleshooting

This sample demonstrates how to dequeue an XML JMS message using a BPEL process and no additional functionality. For example, it doesn’t contain any error handling. Therefore, any errors in the payload will result in exceptions being written to the log file or standard output. If you get any errors related to the payload, such as

Message handle error
...
ORABPEL-09500
...
XPath expression failed to execute.
An error occurs while processing the XPath expression; the expression is 
     /ns2:exampleElement.
...
etc.

check that the variable used in the Java embedding part of the process was entered correctly. Possibly follow the tip mentioned in previous section. If this doesn’t help, you can delete the Java embedding part and simply verify the message via the flow diagram in the Enterprise Manager. Or use a different method, such as writing it to a file via a file adapter.

This concludes this example. In the next post, we will begin with an AQ JMS example, which uses JMS to write to an Advanced Queue stored in the database.

Best regards
John-Brown Evans
Oracle Technology Proactive Support Delivery

Wednesday Nov 21, 2012

JMS Step 3 - Using the QueueReceive.java Sample Program to Read a Message from a JMS Queue

JMS Step 3 - Using the QueueReceive.java Sample Program to Read a Message from a JMS Queue

This post continues the series of JMS articles which demonstrate how to use JMS queues in a SOA context.

In the first post,
JMS Step 1 - How to Create a Simple JMS Queue in Weblogic Server 11g
we looked at how to create a JMS queue and its dependent objects in WebLogic Server.

In the previous post,
JMS Step 2 - Using the QueueSend.java Sample Program to Send a Message to a JMS Queue
I showed how to write a message to that JMS queue using the QueueSend.java sample program.

In this article, we will use a similar sample, the QueueReceive.java program to read the message from that queue. Please review the previous posts if you have not already done so, as they contain prerequisites for executing the sample in this article.

1. Source code

The following java code will be used to read the message(s) from the JMS queue. As with the previous example, it is based on a sample program shipped with the WebLogic Server installation. The sample is not installed by default, but needs to be installed manually using the WebLogic Server Custom Installation option, together with many, other useful samples. You can either copy-paste the following code into your editor, or install all the samples.

The knowledge base article in My Oracle Support:

How To Install WebLogic Server and JMS Samples in WLS 10.3.x (Doc ID 1499719.1)

describes how to install the samples.

QueueReceive.java

package examples.jms.queue;

import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
* This example shows how to establish a connection to
* and receive messages from a JMS queue. The classes in this
* package operate on the same JMS queue. Run the classes together to
* witness messages being sent and received, and to browse the queue
* for messages.  This class is used to receive and remove messages
* from the queue.
*
* @author Copyright (c) 1999-2005 by BEA Systems, Inc. All Rights Reserved.
*/
public class QueueReceive implements MessageListener
{
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

 // Defines the JMS connection factory for the queue.
 public final static String JMS_FACTORY="jms/TestConnectionFactory";

 // Defines the queue.
 public final static String QUEUE="jms/TestJMSQueue";

 private QueueConnectionFactory qconFactory;
 private QueueConnection qcon;
 private QueueSession qsession;
 private QueueReceiver qreceiver;
 private Queue queue;
 private boolean quit = false;

/**
 * Message listener interface.
 * @param msg  message
 */
 public void onMessage(Message msg)
 {
    try {
     String msgText;
     if (msg instanceof TextMessage) {
       msgText = ((TextMessage)msg).getText();
     } else {
       msgText = msg.toString();
     }

     System.out.println("Message Received: "+ msgText );

     if (msgText.equalsIgnoreCase("quit")) {
       synchronized(this) {
         quit = true;
         this.notifyAll(); // Notify main thread to quit
       }
     }
    } catch (JMSException jmse) {
     System.err.println("An exception occurred: "+jmse.getMessage());
    }
 }

 /**
  * Creates all the necessary objects for receiving
  * messages from a JMS queue.
  *
  * @param   ctx    JNDI initial context
  * @param    queueName    name of queue
  * @exception NamingException if operation cannot be performed
  * @exception JMSException if JMS fails to initialize due to internal error
  */
 public void init(Context ctx, String queueName)
    throws NamingException, JMSException
 {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    qcon = qconFactory.createQueueConnection();
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qreceiver = qsession.createReceiver(queue);
    qreceiver.setMessageListener(this);
    qcon.start();
 }

 /**
  * Closes JMS objects.
  * @exception JMSException if JMS fails to close objects due to internal error
  */
 public void close()throws JMSException
 {
    qreceiver.close();
    qsession.close();
    qcon.close();
 }
/**
 * main() method.
 *
 * @param args  WebLogic Server URL
 * @exception  Exception if execution fails
 */

 public static void main(String[] args) throws Exception {
    if (args.length != 1) {
     System.out.println("Usage: java examples.jms.queue.QueueReceive WebLogicURL");
     return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueReceive qr = new QueueReceive();
    qr.init(ic, QUEUE);

    System.out.println(
        "JMS Ready To Receive Messages (To quit, send a \"quit\" message).");

    // Wait until a "quit" message has been received.
    synchronized(qr) {
     while (! qr.quit) {
       try {
         qr.wait();
       } catch (InterruptedException ie) {}
     }
    }
    qr.close();
 }

 private static InitialContext getInitialContext(String url)
    throws NamingException
 {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
 }
}

2. How to Use This Class

2.1 From the file system on Linux

This section describes how to use the class from the file system of a WebLogic Server installation.

Log in to a machine with a WebLogic Server installation and create a directory to contain the source and code matching the package name, e.g. span>$HOME/examples/jms/queue. Copy the above QueueReceive.java file to this directory.

  1. Set the CLASSPATH and environment to match the WebLogic server environment.
    Go to
    $MIDDLEWARE_HOME/user_projects/domains/base_domain/bin  and execute

    . ./setDomainEnv.sh
  2. Collect the following information required to run the script:
  1. The JNDI name of the JMS queue to use
    In the WebLogic server console > Services > Messaging > JMS Modules > Module name, (e.g.
    TestJMSModule) > JMS queue name, (e.g. TestJMSQueue)
    select the queue and note its JNDI name,
    e.g.
    jms/TestJMSQueue
  2. The JNDI name of the connection factory to use to connect to the queue
    Follow the same path as above to get the connection factory for the above queue, e.g. TestConnectionFactory and its JNDI name
    e.g.
    jms/TestConnectionFactory
  3. The URL and port of the WebLogic server running the above queue
    Check the JMS server for the above queue and the managed server it is targeted to, for example soa_server1. Now find the port this managed server is listening on, by looking at its entry under Environment > Servers in the WLS console,
    e.g. 8001
    The URL for the server to be passed to the QueueReceive program will therefore be t3://host.domain:8001
    e.g.
    t3://jbevans-lx.de.oracle.com:8001
  1. Edit Queue Receive .java and enter the above queue name and connection factory respectively under

...
public final static String  JMS_FACTORY="jms/TestConnectionFactory";
...
public final static String QUEUE="jms/TestJMSQueue";
...

  1. Compile Queue Receive .java using

    javac Queue Receive .java
  2. Go to the source’s top-level directory and execute it using

    java examples.jms.queue.Queue Receive   t3://jbevans-lx.de.oracle.com:8001
  3. This will print a message that it is ready to receive messages or to send a “quit” message to end.
  4. The program will read all messages in the queue and print them to the standard output until it receives a message with the payload “quit”.

2.2 From JDeveloper

The steps from JDeveloper are the same as those used for the previous program QueueSend.java, which is used to send a message to the queue. So we won't repeat them here. Please see the previous blog post at
JMS Step 2 - Using the QueueSend.java Sample Program to Send a Message to a JMS Queue
and apply the same steps in that example to the QueueReceive.java program.

This concludes the example. In the following post we will create a BPEL process which writes a message based on an XML schema to the queue.

About

This is the official blog of the SOA Proactive Support Team. Here we will provide information on our activities, publications, product related information and more. Additionally we look forward to your feedback to improve what we do.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today