Java Integration
Transform Anything with Java
All about JMS with Oracle SOA
The first step is to Configure JMS in Weblogic
1. Login to your Weblogic console > domain > Services > Messaging > JMS Servers
2. Click New and name the JMS Server as you wish. Eg : JMSforlearning. Set Persistant Store to none and target it to the domain that you have.
Now the JMS Server should be healthy as the below snapshot

3. Create a JMS Module from Services > Messaging > JMS Modules
4. Click New and leave all the options blank. (jmsModuleforLearning)
5. Create a sub deployment Services > Messaging > JMS Modules > jmsModuleforLearning > SubDeployments > New (Eg: subDepforLearning)
6. We can target the subdeployment to the entire domain or just the JMS Server that we created. Let us choose the JMS server that we created.

7. Create a Connection Factory so that external applications can access our JMS using JNDI
8. Services > Messaging > > JMS Modules > > jmsModuleforLearning > New > Connection Factory

9. Name the connction Factory (Eg: cFactforLearning) and the JNDI Name also (Eg: jms/cFactforLearning).
10. Leave the other options as default. Only during the targeting section, choose the subdeployment we created.

11. The final step is to create a JMS Queue. Follow the same step that we used to create the connec tion factory.
Services > Messaging > JMS Modules > jmsModuleforLearning > New > JMS Queue and name it. Eg: jmsQforLearning and jms/jmsQforLearning
All the options will be same except choosing the subdeployment. The final output should look like below.

The JMS Setup is complete on the weblogic side. Now let us see how to use it through a program.
1. Open JDeveloper and create a generic Java Project and start with creating the java class SendJMSMessage.java and paste the following code in the editor.
package jms;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class SendJMSMessage
{
// Defines the JNDI context factory.
public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
// Defines the JMS context factory.
public final static String JMS_FACTORY="jms/cFactforLearning";
// Defines the queue.
public final static String QUEUE="jms/jmsQforLearning";
private QueueConnectionFactory qconFactory;
private QueueConnection qcon;
private QueueSession qsession;
private QueueSender qsender;
private Queue queue;
private TextMessage msg;
/**
* Creates all the necessary objects for sending
* messages to 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);
qsender = qsession.createSender(queue);
msg = qsession.createTextMessage();
qcon.start();
}
/**
* Sends a message to a JMS queue.
*
* @param message message to be sent
* @exception JMSException if JMS fails to send message due to internal error
*/
public void send(String message) throws JMSException {
msg.setText(message);
qsender.send(msg);
}
/**
* Closes JMS objects.
* @exception JMSException if JMS fails to close objects due to internal error
*/
public void close() throws JMSException {
qsender.close();
qsession.close();
qcon.close();
}
/** main() method.
*
* @param args WebLogic Server URL
* @exception Exception if operation fails
*/
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage: java examples.jms.queue.SendJMSMessage WebLogicURL");
return;
}
InitialContext ic = getInitialContext(args[0]);
SendJMSMessage qs = new SendJMSMessage();
qs.init(ic, QUEUE);
readAndSend(qs);
qs.close();
}
private static void readAndSend(SendJMSMessage qs)
throws IOException, JMSException
{
BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));
String line=null;
boolean quitNow = false;
do {
System.out.print("Enter message (\"quit\" to quit): \n");
line = msgStream.readLine();
if (line != null && line.trim().length() != 0) {
qs.send(line);
System.out.println("JMS Message Sent: "+line+"\n");
quitNow = line.equalsIgnoreCase("quit");
}
} while (! quitNow);
}
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);
}
}
If you are finding any errors, add the libraries that are needed. Mostly weblogic.jar would have to be imported.
Before running we have to create a run configuration to accept the parameters. (Project > Run > Run configuration)

On the run configuration, provide t3://soa-server:port as the parameter. Goto the Tool Settings and check Allow Program Input.

Run > choose the run configuration that you created. There will be an input box. Place the message inside that. Validate the same message in weblogic.


We can also read the message from JMS similar to the way we published. This is called subscribing to the JMS Queue.
package jms;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class getJMSMessage 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/cFactforLearning";
// Defines the queue.
public final static String QUEUE="jms/jmsQforLearning";
private QueueConnectionFactory qconFactory;
private QueueConnection qcon;
private QueueSession qsession;
private QueueReceiver qreceiver;
private Queue queue;
private boolean quit = false;
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.getJMSMessage WebLogicURL");
return;
}
InitialContext ic = getInitialContext(args[0]);
getJMSMessage qr = new getJMSMessage();
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);
}
}
Follow the same process and try the above program.
Now let us see how we can use the JMS from BPEL
1. We will start with reviewing what we have.
cFactforLearning: ConnectionFactory
jmsQforLearning JMS Queue.
2. Now we have to create a connection pool for JMS and update the adapter.
In Weblogic console goto Deployments > jmsAdapter > Configuration > Outbound Connection Pools and expand oracle.tip.adapter.jms.IJmsConnectionFactory > New
Name the JNDI as eis/wls/jmsQforLearning and create a new plan during the next steps.
3. Open the JNDI that was created and update the ConnectionFactoryLocation to the one we created earlier and hit enter. (jms/cFactforLearning)

Note : The next step is to redeploy the jmsAdapter Deployment with the confiruration plan that we created.
4. Goto Deployments > check jmsAdapter > Update. Make sure the correct jmsPlan is selected. Click finish.



5. On the service Adapters choose JMS Adapter and place it in the BPEL Process.
Follow the steps as per the images








Attached is the BPEL code. JMS accepts Base64Binary so I had to add a Java Embedding to make the conversion.
<?xml version = "1.0" encoding = "UTF-8" ?>
<!--
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Oracle JDeveloper BPEL Designer
Created: Tue Sep 09 15:18:22 PDT 2014
Author: bmuthusamy
Type: BPEL 1.1 Process
Purpose: One Way BPEL Process
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-->
<process name="jms_write"
targetNamespace="http://xmlns.oracle.com/POC/JMSWrite/jms_write"
xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:client="http://xmlns.oracle.com/POC/JMSWrite/jms_write"
xmlns:ora="http://schemas.oracle.com/xpath/extension"
xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:ns1="http://xmlns.oracle.com/pcbpel/adapter/jms/POC/JMSWrite/jms_put"
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns2="http://xmlns.oracle.com/pcbpel/adapter/opaque/"
xmlns:bpel2="http://docs.oasis-open.org/wsbpel/2.0/process/executable">
<bpelx:exec import="java.util.*"/>
<bpelx:exec import="java.lang.*"/>
<bpelx:exec import="java.math.*"/>
<bpelx:exec import="java.io.*"/>
<bpelx:exec import="oracle.soa.common.util.*"/>
<!--
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PARTNERLINKS
List of services participating in this BPEL process
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-->
<partnerLinks>
<!--
The 'client' role represents the requester of this service. It is
used for callback. The location and correlation information associated
with the client role are automatically set using WS-Addressing.
-->
<partnerLink name="jms_write_client" partnerLinkType="client:jms_write" myRole="jms_writeProvider"/>
<partnerLink name="jms_put" partnerLinkType="ns1:Produce_Message_plt"
partnerRole="Produce_Message_role"/>
</partnerLinks>
<!--
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VARIABLES
List of messages and XML documents used within this BPEL process
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-->
<variables>
<!-- Reference to the message passed as input during initiation -->
<variable name="inputVariable" messageType="client:jms_writeRequestMessage"/>
<variable name="Invoke1_Produce_Message_InputVariable"
messageType="ns1:Produce_Message_msg"/>
<variable name="inputString" type="xsd:string"/>
<variable name="outputString" type="xsd:base64Binary"/>
</variables>
<!--
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ORCHESTRATION LOGIC
Set of activities coordinating the flow of messages across the
services integrated within this business process
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-->
<sequence name="main">
<!-- Receive input from requestor. (Note: This maps to operation defined in jms_write.wsdl) -->
<receive name="receiveInput" partnerLink="jms_write_client" portType="client:jms_write" operation="process" variable="inputVariable" createInstance="yes"/>
<assign name="AssignInput">
<copy>
<from variable="inputVariable" part="payload"
query="/client:process/client:input"/>
<to variable="inputString"/>
</copy>
</assign>
<bpelx:exec name="Java_Embedding1" version="1.5" language="java">
<![CDATA[String input = (String)getVariableData("inputString");
Base64Encoder Encoder = new Base64Encoder();
try {
String encoded = Encoder.encode(input);
setVariableData("outputString",encoded);
}
catch(Exception uee)
{
uee.printStackTrace();
}]]>
</bpelx:exec>
<assign name="AssignIn">
<copy>
<from variable="outputString"/>
<to variable="Invoke1_Produce_Message_InputVariable" part="opaque"
query="/ns2:opaqueElement"/>
</copy>
</assign>
<invoke name="invokeJMS" bpelx:invokeAsDetail="no"
inputVariable="Invoke1_Produce_Message_InputVariable"
partnerLink="jms_put" portType="ns1:Produce_Message_ptt"
operation="Produce_Message"/>
</sequence>
</process>
Now Deploy the code and test the same. You should be able to see the message in Weblogic too.


Now let us write a service to consume message from JMS
1. Create a SOA Project with empty composite.
2. Drag JMS Adapter into the service Binding Pane and follow the below steps.






3. Just for the exercise, I have created a file adapter to write the content to a file. Below is the adapter configuration.
<adapter-config name="write_to_file" adapter="File Adapter" wsdlLocation="write_to_file.wsdl" xmlns="http://platform.integration.oracle/blocks/adapter/fw/metadata">
<connection-factory location="eis/FileAdapter"/>
<endpoint-interaction portType="Write_ptt" operation="Write">
<interaction-spec className="oracle.tip.adapter.file.outbound.FileInteractionSpec">
<property name="PhysicalDirectory" value="/tmp/"/>
<property name="Append" value="false"/>
<property name="FileNamingConvention" value="test_%yyMMddHHmmssSS%.dat"/>
<property name="NumberMessages" value="1"/>
</interaction-spec>
</endpoint-interaction>
</adapter-config>
Here is the BPEL code.
<?xml version = "1.0" encoding = "UTF-8" ?>
<!--
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Oracle JDeveloper BPEL Designer
Created: Tue Sep 09 17:17:06 PDT 2014
Author: bmuthusamy
Type: BPEL 1.1 Process
Purpose: Empty BPEL Process
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-->
<process name="jms_read"
targetNamespace="http://xmlns.oracle.com/POC/JMS_Read/jms_read"
xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:client="http://xmlns.oracle.com/POC/JMS_Read/jms_read"
xmlns:ora="http://schemas.oracle.com/xpath/extension"
xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:ns1="http://xmlns.oracle.com/pcbpel/adapter/jms/POC/JMS_Read/jms_recieve"
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
xmlns:ns2="http://xmlns.oracle.com/pcbpel/adapter/file/POC/JMS_Read/write_to_file"
xmlns:ns3="http://xmlns.oracle.com/pcbpel/adapter/opaque/">
<!--
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ORCHESTRATION LOGIC
Set of activities coordinating the flow of messages across the
services integrated within this business process
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-->
<partnerLinks>
<partnerLink name="jms_recieve" partnerLinkType="ns1:Consume_Message_plt"
myRole="Consume_Message_role"/>
<partnerLink name="write_to_file" partnerLinkType="ns2:Write_plt"
partnerRole="Write_role"/>
</partnerLinks>
<variables>
<variable name="receive_from_jms_Consume_Message_InputVariable"
messageType="ns1:Consume_Message_msg"/>
<variable name="invoke_write-file_Write_InputVariable"
messageType="ns2:Write_msg"/>
</variables>
<sequence name="main">
<receive name="receive_from_jms" createInstance="yes"
variable="receive_from_jms_Consume_Message_InputVariable"
partnerLink="jms_recieve" portType="ns1:Consume_Message_ptt"
operation="Consume_Message"/>
<assign name="Assign1">
<copy>
<from variable="receive_from_jms_Consume_Message_InputVariable"
part="opaque" query="/ns3:opaqueElement"/>
<to variable="invoke_write-file_Write_InputVariable" part="opaque"
query="/ns3:opaqueElement"/>
</copy>
</assign>
<invoke name="invoke_write-file" bpelx:invokeAsDetail="no"
inputVariable="invoke_write-file_Write_InputVariable"
partnerLink="write_to_file" portType="ns2:Write_ptt"
operation="Write"/>
</sequence>
</process>
Deploy the code and tes the same. If you place a message throught the JMS Write Service, you should geta file created in the /tmp foler.


This concludes our JMS basic tutorial.