This post continues the series of JMS articles which demonstrate how to use JMS queues in a SOA context. The previous posts were:
In this example we will create a BPEL process which will write (enqueue) a message to a JMS queue using a JMS adapter. The JMS adapter will enqueue the full XML payload to the queue.
This sample will use the following WebLogic Server objects. The first two, the Connection Factory and JMS Queue, were created as part of the first blog post in this series, JMS Step 1 - How to Create a Simple JMS Queue in Weblogic Server 11g. If you haven't created those objects yet, please see that post for details on how to do so.
The Connection Pool will be created as part of this example.
As mentioned above, this example uses a WLS Connection Factory called TestConnectionFactory and a JMS queue TestJMSQueue. As these are prerequisites for this example, let us verify they exist.
Log in to the WebLogic Server Administration Console.
Select Services > JMS Modules > TestJMSModule
You should see the following objects:
If not, or if the TestJMSModule is missing, please see the above mentioned article and create these objects before continuing.
The BPEL process we are about to create uses a JMS adapter to write to the JMS queue. The JMS adapter is deployed to the WebLogic server and needs to be configured to include a connection pool which references the connection factory associated with the JMS queue.
The JMS adapter configuration is complete and it can now be used to access the JMS queue.
To summarize: we have created a JMS adapter connection pool connector with the JNDI name jms/TestConnectionFactory. This is the
JNDI name to be accessed by a process such as a BPEL process, when using the JMS adapter to access the previously created JMS queue
with the JNDI name jms/TestJMSQueue.
In the following step, we will set up a BPEL process to use this JMS adapter to write to the JMS queue.
This step requires that you have a valid Application Server Connection defined in JDeveloper, pointing to the application server on which you created the JMS Queue and Connection Factory. You can create this connection in JDeveloper under the Application Server Navigator. Give it any name and be sure to test the connection before completing it. This sample will use the connection name jbevans-lx-PS5, as that is the name of the connection pointing to my SOA PS5 installation.
When using a JMS adapter from within a BPEL process, there are various configuration options, such as the operation type (consume
message, produce message etc.), delivery mode and message type. One of these options is the choice of the format of the JMS message
payload. This can be structured around an existing XSD, in which case the full XML element and tags are passed, or it can be opaque,
meaning that the payload is sent as-is to the JMS adapter. In the case of an XSD-based message, the payload can simply be copied to
the input variable of the JMS adapter. In the case of an opaque message, the JMS adapter’s input variable is of type base64binary. So the payload needs to be converted to base64 binary first. I will go into this in more detail in a later blog entry.
This sample will pass a simple message to the adapter, based on the following simple XSD file, which consists of a single string element:
<?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>
The following steps are all executed in JDeveloper. The SOA project will be created inside a JDeveloper Application. If you do not
already have an application to contain the project, you can create a new one via File > New > General > Generic Application.
Give the application any name, for example JMSTests and, when prompted for a project name and type, call the projectJmsAdapterWriteWithXsd and select SOA as the project technology type. If you already have an application, continue below.
Create a new project and choose SOA Tier > SOA Project as its type. Name it JmsAdapterWriteSchema. When prompted for the composite
type, choose Composite With BPEL Process.
When prompted for the BPEL Process, name it JmsAdapterWriteSchema too and choose Synchronous BPEL Process as the template.
This will create a composite with a BPEL process and an exposed SOAP service. Double-click the BPEL process to open and begin editing it. You should see a simple BPEL process with a Receive and Reply activity. As we created a default process without an XML schema, the
input and output variables are simple strings.
An XSD file is required later to define the message format to be passed to the JMS adapter. In this step, we create a simple XSD
file, containing a string variable and add it to the project. First select the xsd item in the left-hand navigation tree to ensure
that the XSD file is created under that item.
Select File > New > General > XML and choose XML Schema.
Call it stringPayload.xsd and when the editor opens, select the Source view.
then replace the contents with the contents of the stringPayload.xsd example above and save the file. You should see it under the xsd
item in the navigation tree.
We will create the JMS adapter as a service at the composite level.
If it is not already open, double-click the composite.xml file in
the navigator to open it.
From the Component Palette, drag a JMS adapter over onto the
right-hand swim lane, under External References.
This will start the JMS Adapter Configuration Wizard. Use the following entries:
Service Name: JmsAdapterWrite
Oracle Enterprise Messaging Service (OEMS): Oracle Weblogic JMS
AppServer Connection: Use an existing application server connection pointing to the WebLogic server on which the above JMS queue and connection factory were created. You can use the “+” button to create a connection directly from the wizard, if you do not already have one. This example uses a connection called jbevans-lx-PS5.
Adapter Interface > Interface: Define from operation and schema (specified later)
Operation Type: Produce Message
Operation Name: Produce_message
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 earlier.
JNDI Name: The JNDI name to use for the JMS connection. This is probably the most important step in this exercise and 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.)
URL: We will use the XSD file we created earlier, stringPayload.xsd to define the message format for the JMS adapter. Press the magnifying glass icon to search for schema files. Expand Project Schema Files > stringPayload.xsd and select exampleElement: string.
Press Next and Finish, which will complete the JMS Adapter configuration.
In this step, we link the BPEL process/component to the JMS adapter. From the composite.xml editor, drag the right-arrow icon from the
BPEL process to the JMS adapter’s in-arrow.
This completes the steps at the composite level.
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
JmsAdapterWriteSchema.bpel file. This will display the BPEL process in the design view. You should see the JmsAdapterWrite partner link under one of the two swim lanes. We want it in the right-hand swim lane. If JDeveloper displays it in the left-hand lane, right-click it and choose Display > Move To Opposite Swim Lane.
An Invoke activity is required in order to invoke the JMS adapter. Drag an Invoke activity between the Receive and Reply activities. Drag the right-hand arrow from the Invoke activity to the JMS adapter partner link. This will open the Invoke editor. The correct default values are entered automatically and are fine for our purposes. We only need to define the input variable to use for the JMS adapter. By pressing the green “+” symbol, a variable of the correct type can be auto-generated, for example with the name Invoke1_Produce_Message_InputVariable.
Press OK after creating the variable.
(For some reason, while I was testing this, the JMS Adapter moved back to the left-hand swim lane again after this step. There
is no harm in leaving it there, but I find it easier to follow if it is in the right-hand lane, because I kind-of think of the message coming in
on the left and being routed through the right. But you can follow your personal preference here.)
Drag an Assign activity between the Receive and Invoke activities. We will simply copy the input variable to the JMS adapter and, for completion, so the process has an output to print, again to the process’s output variable.
Double-click the Assign activity and create two Copy rules:
for the first, drag Variables > inputVariable > payload > client:process > client:input_string to Invoke1_Produce_Message_InputVariable > body > ns2:exampleElement
for the second, drag the same input variable to outputVariable > payload > client:processResponse > client:result
This will create two copy rules, similar to the following:
This completes the BPEL and Composite design.
We won’t go into too much detail on how to compile and deploy.
In JDeveloper, compile the process by pressing the Make or Rebuild icons or by right-clicking the project name in the navigator and
selecting Make... or Rebuild...
If the compilation is successful, deploy it to the SOA server connection defined earlier. (Right-click the project name in the navigator, select Deploy to Application Server, choose the application server connection, choose the partition on the server (usually default) and press Finish. You should see the message
---- Deployment finished. ----
in the Deployment frame, if the deployment was successful.
This is the exciting part.
Open two tabs in your browser and log in to the WebLogic Administration Console in one tab and the Enterprise Manager 11g Fusion Middleware Control (EM) for your SOA installation in the other. We will use the Console to monitor the messages being written to the queue and the EM to execute the composite.
In the Console, go to Services > Messaging > JMS Modules > TestJMSModule > TestJMSQueue > Monitoring. Note the number of messages under Messages Current.
In the EM, go to SOA > soa-infra (soa_server1) > default (or wherever you deployed your composite to) and click on JmsAdapterWriteSchema
[1.0], then press the Test button.
Under Input Arguments, enter any string into the text input field for the payload, for example Test Message then press Test Web Service.
If the instance is successful you should see the same text in the Response message, “Test Message”.
In the Console, refresh the Monitoring screen to confirm a new message has been written to the queue.
Check the checkbox and press Show Messages. Click on the newest message and view its contents. They should include the full XML of
the entered payload.
If you get an exception similar to the following at runtime
... BINDING.JCA-12510 JCA Resource Adapter location error. Unable to locate the JCA Resource Adapter via .jca binding file element
then this is very likely due to an incorrect JNDI name entered for the JMS Connection in the JMS Adapter Wizard. Recheck those steps.
The error message prints the name of the JNDI name used. In this example, it was incorrectly entered as eis/wls/QueueTest instead
This concludes this example.