Showing posts with label Apache Camel. Show all posts
Showing posts with label Apache Camel. Show all posts

Saturday, June 11, 2016

Apache Camel: Integrating Weblogic Queue with Jboss Fuse ESB

This is article is about to integrate the Weblogic Message broker with Jboss Fuse using Apche Camel integration framework. For this I assume that you already have a weblogic server in place with JMS queue. I'm not going in detail to explain more about Weblogic message broker, Apache Camel, Jboss fuse, OSGi.

The requirement for this integrations,
  1. Jboss Fuse ESB 6.1
  2. Apache Camel
  3. Eclipse
  4. Weblogic Server with Queue Configuration
  5. wlthint3client.jar [Download from official page of Weblogic server]
Now we required below details of your WL server,
  1. Weblogic broker URL with port
  2. Credentials for this URL to connect (username, password)
  3. Weblogic JNDI Name exposed for communication with queue
  4. Weblogic queue name
Here, for this integration I have used as per below,

WL broker URL -->  t3://localhost:8090
Credentials -->  Username : wl_admin, password : wl_pass
WL JNDI Name -->  jms/TestJndiName
WL Queue Name -->  testqueue

We are done with the configuration related requirement. So, let's do camel riding for this integration.

To send and received data with WL queue we need to create one camel component which will do our job. This component will be responsible for exchange data with WL queue. To create this component we required object of jndiTemplate, jndiObjectFactoryBean, jndiDestinationResolver and jmsConfiguration. Each of this object we can refer respective java docs. Will explain each of the required object in the next section. 

jndiTemplate

This is the helper class which specify JNDI operations. It provides methods to lookup and bind objects, and allows implementations of the JndiCallback interface to perform any operation they like with a JNDI naming context provided. Here we have specified all the required properties which is required to lookup exposed JNDI object.

 Ref: Spring Docs


jndiObjectFactoryBean

This exposes the singleton object found in JNDI for bean references in a application context. The default behavior of this object is to lookup the object on startup and cache it. We can change its behavior to lazy initialization by setting lookupOnStartup=false and setting proxyInterface=javax.jms.ConnectionFactory. You can have more detail on this by referring spring docs. The simple code snippet is like this,


jndiDestinationResolver

This allows for customizing the JNDI environment if necessary, for example specifying appropriate JNDI environment properties. Dynamic queues and topics get cached by destination name. As a consequence, you need to use unique destination names across both queues and topics. You can have more detail on this by referring spring docs. The simple code snippet is like this,


jmsConfiguration
This object holds all the configuration and required object which are needed to create the camel weblogic component which exchanges the data between fuse and WL. The simple code snippet is like this,
wlqueue

This is the camel component with which we will access the queue/topic to send or receive the messages to/from WL.

Full context file is as per below,

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:camel="http://camel.apache.org/schema/spring"
  
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd
  http://camel.apache.org/schema/spring 
  http://camel.apache.org/schema/spring/camel-spring.xsd">

<!-- JNDITemplate object which holds basic property for JNDI lookup -->
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
   <property name="environment">
       <props>
           <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
           <prop key="java.naming.provider.url">t3://localhost:8090</prop>
           <prop key="java.naming.security.principal">wl_admin</prop>
           <prop key="java.naming.security.credentials">wl_pass</prop>
       </props>
   </property>
</bean>
<!-- jndiObjectFactoryBean object -->
<bean id="jndiObjectFactoryBean" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName" value="jms/TestJndiName"/>
   <property name="jndiTemplate" ref="jndiTemplate"/>
   <property name="lookupOnStartup" value="false"/> <!--  -->
   <property name="proxyInterface" value="javax.jms.ConnectionFactory"/>
</bean>
<!-- jndiDestinationResolver object -->
<bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
   <property name="jndiTemplate" ref="jndiTemplate"/>
</bean>
<!-- jmsConfiguration object -->
<bean id="jmsConfiguration" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jndiObjectFactoryBean"/>
<property name="destinationResolver" ref="jndiDestinationResolver"/>
</bean>
<!-- wlqueue object -->
<bean id="wlqueue" class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration" ref="jmsConfiguration" />
</bean>
<camel:routeContext id="main-weblogic-consumer-producer-route-context">
<!-- This route will process by consuming weblogic queue  -->
<camel:route id="simple-weblogic-consumer-route">
<camel:from uri="wlqueue:queue:testqueue" />
<log loggingLevel="DEBUG" logName="simple-weblogic-consumer-route" 
message="Consumed message from weblogic queue:testqueue :: ${body}" />
<camel:to uri="direct:consumer-message-process-route" />
</camel:route>

<camel:route id="consumer-message-process-route">
<camel:from uri="direct:consumer-message-process-route" />
<log loggingLevel="DEBUG" logName="consumer-message-process-route" 
message="Processing initiated for consumed message :: ${body}" />
</camel:route>
<camel:route id="message-creater-for-wl-producer-route">
<camel:from uri="file://some-dir/file/input" />
<log loggingLevel="DEBUG" logName="message-creater-for-wl-producer-route" 
message="Message for web logic queue :: ${body}" />
<camel:to uri="direct:simple-weblogic-producer-route" />
</camel:route>
<!-- This route will push message in weblogic queue  -->
<camel:route id="simple-weblogic-producer-route">
<camel:from uri="direct:simple-weblogic-producer-route" />
<log loggingLevel="DEBUG" logName="simple-weblogic-consumer-route" 
message="Message to be push in weblogic queue:testqueue :: ${body}" />
<camel:to uri="wlqueue:queue:testqueue" />
</camel:route>
</camel:routeContext>
</beans>

Here, I have created route which consume message from WL queue and to push the message in the WL queue.

Now, our module is ready to exchange messages between web logic and jboss fuse esb. Generate OSGi using maven. Before deploying your bundle you have to install wlthint3client.jar in fuse server. To install this jar file you to convert it into OSGi bundle. Don't worry for this conversion. Below command will convert your jar into OSGi and will deploy into fuse esb.

Start your jboss fuse server and login to karaf console. fire below command to install wlthint3client.jar in fuse server. 

$osgi:install -s wrap:file:///<absolute-path>/wlthint3client.jar

Once you deployed this now you need to deploy you osgi module in jboss fuse. 


We are done now. That's it. Try to push message in WL queue and observe fuse server log.

Don't forget to share your feedback to make this article more helpful.

Cheers,
Ashish Mishra

Saturday, May 14, 2016

Java Integration with Oracle Tuxedo using JCA Adapter

Today's article is about integrating Tuxedo based system with J2EE using Application Server. I think this article will helpful if you are looking to integrate tuxedo system with J2EE application. So, let us begin this integration.

For this article I have used Jboss EAP/AS as a application server, Orcale Tuxedo Adapter and Java based web application. I assume that you guys have basic knowledge of JBoss AS configuration, java web based application and JCA and have some basic idea about Tuxedo System.

Now, you have to setup the environment so we can start the development.
Download Jboss Application Server(6.xxx) or Jboss EAP(6.xxx) from official Redhat
Download Tuxedo JCA connector from Oracle official site. You can have introductory knowledge by referring Data sheet pdf file.

Ref. Oracle


Note, we will have imaginary Tuxedo system because configuring Tuxedo system is tedious job and again its one big topic. You can have basic understanding from  Data Sheet of Oracle Tuxedo document. I think this will help you guys to get basic knowledge of Tuxedo.

Ref. Oracle
I think this is sufficient to have basic knowledge of Tuxedo and Tuxedo Adapter based on JCA provided by Oracle.

Now, after environment  is ready please check Jboss server should be up and functioning without any failure. You can check Jboss server admin console by typing in your browser http://127.0.0.1:9990. It will ask for username and password. You provide whatever you have given at the time of user creation with Jboss.

Jboss Configuration :
Once server is up and running, we need to do some configuration changes in Jboss AS as per below which is required to deploy the Tuxedo JCA Adapter in server,

  1. Need to disable archive-validation in $JbossAS\standalone\configuration\standalone.xml
      2. Need to add resource-adapters entry in $JbossAS\standalone\configuration\standalone.xml
      
....        <subsystem xmlns="urn:jboss:domain:pojo:1.0"/>
        <subsystem xmlns="urn:jboss:domain:remoting:1.1">
            <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
        </subsystem>
        <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0">
            <resource-adapters>
                <resource-adapter>
                    <archive>com.oracle.tuxedo.TuxedoAdapter.rar</archive>
                    <transaction-support>LocalTransaction</transaction-support>
                    <config-property name="traceLevel">80000</config-property>
                    <config-property name="xaAffinity">true</config-property>
                    <config-property name="dmconfig">
                       $JbossAS/standalone/configuration/dmconfig.xml
                    </config-property>
                    <connection-definitions>
                        <connection-definition class-name="javax.resource.cci.ConnectionFactory" jndi-name="java:tuxedo/Connection" enabled="true" use-java-context="true" pool-name="Connection" use-ccm="true">
                            <pool>
                                <min-pool-size>0</min-pool-size>
                                <max-pool-size>10</max-pool-size>
                                <prefill>false</prefill>
                                <use-strict-min>false</use-strict-min>
                                <flush-strategy>FailingConnectionOnly</flush-strategy>
                            </pool>
                            <security>
                                <application/>
                            </security>
                        </connection-definition>
                    </connection-definitions>
                </resource-adapter>
            </resource-adapters>
        </subsystem>
        <subsystem xmlns="urn:jboss:domain:sar:1.0"/>
        <subsystem xmlns="urn:jboss:domain:security:1.1">
     .....
In this we have to note that we have exposed JNDI context with name java:tuxedo/Connection for Tuxedo Adapter in Jboss container. The same will be used to  create a connection object to do transaction with Tuxedo system.

Tuxedo JCA Adapter Configuration:
We are done with Jboss AS configuration. Now we will do Tuxedo Adapter internal configuration to connect real Tuxedo based system. Tuxedo JCA adapter is bundled as a rar file like com.oracle.tuxedo.TuxedoAdapter.rar. Follow below configuration with Tuxedo Adapter

1) Remove dmconfig.xml fle from adapter .rar file and placed it into $JbossAS\standalone\configuration. Later we will modify it for connection and transaction. Below files and jar files are the part of the adapter.
 

Also, we need to remove all the files from META-INF dir except ra.xml and MANIFEST.MF. Later we will update the ra.xml file as per our requirement.




2) Copy all the jar files which is available inside adapter into your web app from where we will get the connection from JNDI and do the programming to send data to Tuxedo system.

3) Modification in dmconfig.xml as per below. It varies as per your requirement. This file contains Tuxedo system related configuration. Configuration like, local access point, remote access point, session profile, session, exposed services by Tuxedo System. I'm not going to explain more about this file, you can learn it from official oracle web site. But for reference you can refer this site. This is the key file which is used by tuxedo adapter to establish connection and trigger the request based on exposed services by Tuxedo System.
dmconfig.xml :

<?xml version="1.0" encoding="UTF-8"?>
<TuxedoConnector>
<!-- Local Access point from where Tuxedo System is being called,
Your server IP and your server IP needs to be configured at Tuxedo System
as remote access point
-->
<LocalAccessPoint name="local_acc_point">
<AccessPointId>local_acc_point_id</AccessPointId>
<NetworkAddress>//localhost:8080</NetworkAddress>
</LocalAccessPoint>
<!-- 
Remote Tuxedo System IP along with port
-->
<RemoteAccessPoint name="remote_acc_point">
<AccessPointId>remote_acc_point_id</AccessPointId>
<NetworkAddress>//remote.tuxedo.system.host.endpoint:port</NetworkAddress>
</RemoteAccessPoint>
<!-- 
Basic configuration to establish session with Tuxedo System.
-->
<SessionProfile name="profile_1">
<Security>NONE</Security>
<BlockTime>30000</BlockTime>
<Interoperate>false</Interoperate>
<ConnectionPolicy>ON_DEMAND</ConnectionPolicy>
<ACLPolicy>local</ACLPolicy>
<CredentialPolicy>local</CredentialPolicy>
<RetryInterval>60</RetryInterval>
<MaxRetries>1000</MaxRetries>
<CompressionLimit>1000000</CompressionLimit>
<KeepAlive>100000</KeepAlive>
<KeepAliveWait>200000</KeepAliveWait>
</SessionProfile>
<!-- 
This session will be used by Tuxedo Adapter for transaction by
using session profile and remote/loca access point.
-->
<Session name="session_1">
<LocalAccessPointName>local_acc_point</LocalAccessPointName>
<RemoteAccessPointName>remote_acc_point</RemoteAccessPointName>
<ProfileName>profile_1</ProfileName>
</Session>
<Import name="TOUPPER">
    <RemoteName>TOUPPER</RemoteName>
    <SessionName>session_1</SessionName>
    <LoadBalancing>RoundRobin</LoadBalancing>
  </Import>
  <Import name="ECHO">
    <RemoteName>ECHO</RemoteName>
    <SessionName>session_1</SessionName>
    <LoadBalancing>RoundRobin</LoadBalancing>
  </Import>
   <!-- More than one  Import will be configured here as per the Tuxedo services exposed -->
  <Import name="Service_Name_1">
    <RemoteName>Service_Name_1</RemoteName>
    <SessionName>session_1</SessionName>
    <LoadBalancing>RoundRobin</LoadBalancing>
  </Import>
  <Import name="Service_Name_2">
    <RemoteName>Service_Name_2</RemoteName>
    <SessionName>session_1</SessionName>
    <LoadBalancing>RoundRobin</LoadBalancing>
  </Import>
</TuxedoConnector>


4)
Need to modify the Adapter's ra.xml as I did. Here, we have to make sure the dmconfig.xml file should be correctly placed and correctly configured in this file.This configuration is used internally by Tuxedo Adapter. You can read more about this file from here.
ra.xml :
<?xml version="1.0" encoding="UTF-8"?>
<connector xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
    version="1.5">
<display-name>Tuxedo JCA Adapter</display-name>
<vendor-name>Oracle</vendor-name>
<eis-type>Tuxedo</eis-type>
<resourceadapter-version>11gR1(11.1.1.2.1)</resourceadapter-version>
<license>
<description>Tuxedo SALT license</description>
<license-required>false</license-required>
</license>
<resourceadapter>
<resourceadapter-class>com.oracle.tuxedo.adapter.TuxedoResourceAdapter</resourceadapter-class>
<config-property>
<config-property-name>debugConfig</config-property-name>
<config-property-type>java.lang.Boolean</config-property-type>
<config-property-value>true</config-property-value>
</config-property>
<config-property>
<config-property-name>traceLevel</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>100000</config-property-value>
</config-property>
<config-property>
<config-property-name>xaAffinity</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>true</config-property-value>
</config-property>
<config-property>
<config-property-name>dmconfig</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>$JbossAS/standalone/configuration/dmconfig.xml</config-property-value>
</config-property>
<outbound-resourceadapter>
<connection-definition>
<managedconnectionfactory-class>com.oracle.tuxedo.adapter.spi.TuxedoManagedConnectionFactory</managedconnectionfactory-class>
<connectionfactory-interface>javax.resource.cci.ConnectionFactory</connectionfactory-interface>
<connectionfactory-impl-class>com.oracle.tuxedo.adapter.cci.TuxedoConnectionFactory</connectionfactory-impl-class>
<connection-interface>javax.resource.cci.Connection</connection-interface>
<connection-impl-class>com.oracle.tuxedo.adapter.cci.TuxedoJCAConnection</connection-impl-class>
</connection-definition>
<transaction-support>LocalTransaction</transaction-support>
<authentication-mechanism>
<authentication-mechanism-type>BasicPassword</authentication-mechanism-type>
<credential-interface>javax.resource.spi.security.PasswordCredential</credential-interface>
</authentication-mechanism>
<reauthentication-support>false</reauthentication-support>
</outbound-resourceadapter>
</resourceadapter>
</connector>


We almost completed configuration related things for this integration. So, let's do some programming now.

Application Programming:
Create one web application say it test-tuxedo-connector. Create one jsp and one servlet. From servlet create one service class from where we will prepare tuxedo request and will establish a connection with Tuxedo system and post our request to Tuxedo system. Let's move step by step.

1) Create a jsp-servlet based web app. Include a jars file in web-inf/lib directory from adapter.rar file which I explained earlier.Add this jars in the classpath of your web app.

2) I assume that you have already read about Tuxedo based system and aware with .FML file(Field Mapping List). Basically in this file all the fields and services are defined. This file is similar like wdl and xsd file for SOAP based web services. This is the mapping file in which fields are defined which are used in Tuxedo system along with data type. I have used below test.fml file in this example.


3) Need to create java class in which all the fields are mapped with respect to test.fml. Going to say this class as TuxedoFmlTable.java. In this class we have to create unique integer value for each of the field defined in test.fml. We are going to create one utility class which creates unique numeric value by using test.fml.

public class TuxedoFmlFieldsCreater extends weblogic.wtc.jatmi.DynamicFldTbl{
static final String USER_FML_TABLE_FILE = "<file_location_of_fml_file>\\test.fml";
public TuxedoFmlFieldsCreater() {
super(USER_FML_TABLE_FILE, true);
}
public static void main(String[] args) {
TuxedoFieldTable bf = new TuxedoFieldTable();
String[] list = bf.getFldNames();
for (int i = 0; i < list.length; i++ )
System.out.println("FieldName = [" + list[i] + "], FieldId = [" + bf.name_to_Fldid(list[i]) + "]");

System.out.println("Total entries = " + list.length);
}
}

Output of above class file.

TuxedoFmlTable.java

import java.util.Hashtable;
import weblogic.wtc.jatmi.FldTbl;

public class TuxedoFmlTable implements FldTbl{
Hashtable<String, Integer> nameToFieldTable;
Hashtable<Integer, String> fieldToNameTable;

public final static int TST_DATE = 167772161;
public final static int TST_TIME = 167772162;
public final static int TST_MSGNAME = 167772163;
public final static int TST_CONTEXTID = 33554436;
public final static int TST_USERID = 167772165;
public final static int TST_ERRORNUM = 33554438;
public final static int TST_STATUSTEXT = 167772167;
public final static int TST_STATUSFLAG = 167772168;

public TuxedoFmlTable(){
if(nameToFieldTable == null || nameToFieldTable.isEmpty()){
nameToFieldTable = new Hashtable<String, Integer>(9, 0.75f);

nameToFieldTable.put("TST_DATE", TST_DATE);
nameToFieldTable.put("TST_TIME", TST_TIME);
nameToFieldTable.put("TST_MSGNAME", TST_MSGNAME);
nameToFieldTable.put("TST_CONTEXTID", TST_CONTEXTID);
nameToFieldTable.put("TST_USERID", TST_USERID);
nameToFieldTable.put("TST_ERRORNUM", TST_ERRORNUM);
nameToFieldTable.put("TST_STATUSTEXT", TST_STATUSTEXT);
nameToFieldTable.put("TST_STATUSFLAG", TST_STATUSFLAG);
}

if(fieldToNameTable == null || fieldToNameTable.isEmpty()){
fieldToNameTable = new Hashtable<Integer, String>(9, 0.75f);

fieldToNameTable.put(TST_DATE, "TST_DATE");
fieldToNameTable.put(TST_TIME, "TST_TIME");
fieldToNameTable.put(TST_MSGNAME, "TST_MSGNAME");
fieldToNameTable.put(TST_CONTEXTID, "TST_CONTEXTID");
fieldToNameTable.put(TST_USERID, "TST_USERID");
fieldToNameTable.put(TST_ERRORNUM, "TST_ERRORNUM");
fieldToNameTable.put(TST_STATUSTEXT, "TST_STATUSTEXT");
fieldToNameTable.put(TST_STATUSFLAG, "TST_STATUSFLAG");
}
}

@Override
public String Fldid_to_name(int fldId) {
return ((String) fieldToNameTable.get(new Integer(fldId)));
}

@Override
public String[] getFldNames() {
String[] fieldNames = {
"TST_DATE","TST_TIME","TST_MSGNAME","TST_CONTEXTID",
"TST_USERID","TST_ERRORNUM","TST_STATUSTEXT","TST_STATUSFLAG"
};
return fieldNames;
}

@Override
public int name_to_Fldid(String fieldName) {
Integer fldId = nameToFieldTable.get(new String(fieldName));
if (fldId == null) {
return (-1);
} else {
return (fldId.intValue());
}
}
}


4) We have created all the basic class which is required to created FML32 object which is going to send by our web app to tuxedo system via adapter. I assume that you have created web apps in which you have created one servelt and jsp page from where you will trigger the request and which will be served by servlet. Here in below class I will explain to create an tuxedo connection object through JNDI lookup from in Jboss server. We have already deploy the adapter in $JbossAS\standalone\deployments and hope its successfully deployed. We have already exposed java:tuxedo/Connection.

Full implementation of the main class where we are creating connection and posting data to tuxedo system via adapter.

TuxedoExecutor.java

import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.Interaction;
import javax.resource.cci.InteractionSpec;
import weblogic.wtc.jatmi.TypedFML32;
import com.oracle.tuxedo.adapter.cci.TuxedoFML32Record;
import com.oracle.tuxedo.adapter.cci.TuxedoInteractionSpec;

public class TuxedoExecutor {
private static Context contextObj = null;
private static ConnectionFactory conFactoryObj = null;
private static TuxedoFmlTable fmlTable = null;

private void createTuxedoConnectionFactory() throws NamingException, Exception {
try {
if(contextObj == null)
contextObj = new InitialContext();
if(conFactoryObj == null)
conFactoryObj = (ConnectionFactory) contextObj.lookup("java:tuxedo/Connection");
} catch (NamingException ne) {
throw ne;
} catch (Exception e) {
throw e;
}
}

public Connection getTuxedoConnection() throws Exception{
Connection connection = null;
try {
if(conFactoryObj == null)
createTuxedoConnectionFactory();
connection = conFactoryObj.getConnection();
} catch (Exception e) {
throw e;
}
return connection;
}

public void postDataToTuxedoSystem(Map<String, String> paramMap) throws Exception{
Connection tuxConObj = null;
Interaction tuxInteraction = null;
TuxedoInteractionSpec tuxInterSpec = null;
try {
if(fmlTable == null)
fmlTable = new TuxedoFmlTable();
tuxConObj = getTuxedoConnection(); 
tuxInteraction = tuxConObj.createInteraction();
tuxInterSpec = new TuxedoInteractionSpec();
tuxInterSpec.setFunctionName("");
tuxInterSpec.setInteractionVerb(InteractionSpec.SYNC_SEND_RECEIVE);
TypedFML32 inFml32 = new TypedFML32(fmlTable);
//Setting key-value in inFml32 object
inFml32.Fchg(fmlTable.name_to_Fldid("TST_DATE"), new Short((short)0), paramMap.get("TST_DATE").trim());
inFml32.Fchg(fmlTable.name_to_Fldid("TST_TIME"), new Short((short)0), paramMap.get("TST_TIME").trim());
inFml32.Fchg(fmlTable.name_to_Fldid("TST_MSGNAME"), new Short((short)0), paramMap.get("TST_MSGNAME").trim());
inFml32.Fchg(fmlTable.name_to_Fldid("TST_CONTEXTID"), new Short((short)0), paramMap.get("TST_CONTEXTID").trim());
inFml32.Fchg(fmlTable.name_to_Fldid("TST_USERID"), new Short((short)0), paramMap.get("TST_USERID").trim());
inFml32.Fchg(fmlTable.name_to_Fldid("TST_ERRORNUM"), new Short((short)0), paramMap.get("TST_ERRORNUM").trim());
//inFml32.Fchg(fmlTable.name_to_Fldid("TST_STATUSTEXT"), new Short((short)0), paramMap.get("TST_STATUSTEXT").trim());
//inFml32.Fchg(fmlTable.name_to_Fldid("TST_STATUSFLAG"), new Short((short)0), paramMap.get("TST_STATUSFLAG").trim());

TuxedoFML32Record inRecord = new TuxedoFML32Record(inFml32);
TypedFML32 outFml32 = new TypedFML32(fmlTable);
TuxedoFML32Record outRecord = new TuxedoFML32Record(outFml32);
//This will execute our requet to Tuxedo system via adapter
tuxInteraction.execute(tuxInterSpec, inRecord, outRecord);
if(outRecord.getTperrno() == 0){
System.out.println("Transaction Successful.");
//Fetching details from the outRecord
TypedFML32 fml32 = outRecord.getFML32();
String statusText = (String) fml32.Fget(fmlTable.name_to_Fldid("TST_STATUSTEXT"), new Short((short)0));
String statusFlag = (String) fml32.Fget(fmlTable.name_to_Fldid("TST_STATUSFLAG"), new Short((short)0));
} else {
System.out.println("Some problem occurred during the transaction.");
System.out.println("Tperrno : " + outRecord.getTperrno());
System.out.println("Tpurcode : " + outRecord.getTpurcode());
System.out.println("Tperrordetail : " + outRecord.getTperrordetail());
}
} catch (Exception e) {
throw e;
}
finally {
if(tuxInteraction != null)
tuxInteraction.close();
if(tuxConObj != null)
tuxConObj.close();
}
}
}


We are done now. Once you are ready with all this than please deploy your web application in the same directory where we have deployed the adapter. Our application should be deployed successfully. Now you trigger the request and observe the log in your system as well as in Tuxedo system which you wish to connect.

Please don't forget to give your input to make this article more helpful.

Cheers,
Ashish Mishra

Sunday, July 26, 2015

Apache Camel: Integration with JMS and ActiveMQ

Today, I will explain about how to work with JMS(Java Message Service) in your SOA/ESB. JMS is powerful API to exchange data between different systems now days. I am not going to in depth of JMS. I will explain just basic of it. To use JMS we require some middleware message broker which persist data for sometime. There mainly two ways of exchanging the data. 1) Point-to-Point (Queue) 2) Publish-Subscribe (Topic). You can use any of them based on your business requirement.

Point-to-Point

Publisher-Subscribers

Reference : JavaTPoint. You can read more details of JMS from given reference.

JMS Flow

Now, Let me give some basic about middleware message broker in SOA/ESB based applications. Message Broker is the tools which is placed between producer and consumer to exchange the data using formal messaging protocol. You can have clear picture by referring below images which I found on RedHat portal. There are many provider of message brokers. The notable and popular brokers are ActiveMQ and RabbitMQ. Here, I have used ActiveMQ as middleware message broker. You can read more about ActiveMQ from here.

Reference: RedHat
Now, Let's Integrate JMS and ActiveMQ using Apache Camel. We will go step by step to configure the JMS and ActiveMQ in using Apache Camel in Jboss Fuse ESB. I hope, you have already setup the all the things to build and run camel based apps in Jboss Fuse ESB.

Step 1: To add JMS and ActiveMQ maven dependency in your project.
Add below lines of code in your projects pom.xml.

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jms</artifactId>
    <version>x.x.x</version>
    <!-- Your camel's version -->
</dependency>

<dependency>
   <groupId>org.apache.activemq</groupId>
   <artifactId>activemq-pool</artifactId>
   <version>x.x.x</version>
   <!-- Check Apache Camel's version and find the appropriate activemq version -->
</dependency>

After adding this clean and build your project so, maven can load the dependent library in //users/.m2

Step 2: Create activemq.xml
Creates the activemq.xml in which you have to define the where to store the messages which comes to ActiveMQ. What are the broker name, what is the default directory for storage, what will be the persistence adapter for storage, memory usage etc. Place this file in the server classpath or conf directory from where the server looks up config related things.

For Jboss Fuse ESB, you should place this activemq.xml in etc folder of your server. Please verify that this is added in the config file with name activemq-karaf-{activemq-karaf-version}.redhat-{fuse-version}-activemq.cfg. In this file you can find the ActiveMQ related configuration like as per below and this file reside in
\\server-base-dir\system\org\apache\activemq\activemq-karaf\{activemq-karaf-version}.redhat-{fuse-version}

broker-name=amq-broker
data=${karaf.data}/${broker-name}
config=${karaf.base}/etc/activemq.xml

Now, let's add the beans related to ActiveMQ and routes which produce and consume the message to from ActiveMQ message broker. I will also show how to send/receive to/from queue and topic.

Below are the beans which manage the transactions to exchange the messages between camel and ActiveMQ,

        <bean id="activeMQConFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
<property name="userName" value="userName_activemq"></property>
<property name="password" value="password_activemq"></property>
</bean>

<bean id="pooledConFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
init-method="start" destroy-method="stop">
<property name="maxConnections" value="5" />
<property name="connectionFactory" ref="activeMQConFactory" />
</bean>

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConFactory" />
<property name="concurrentConsumers" value="5" />
</bean>

<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
</bean>

JMS Queue: Produce and consume messages using JMS Queue. Add below routes in your camel context file.

<!-- Route which sends message to the jms-queue with name test-queue -->

<camel:route id="MessageSenderToJMSQueue">
<camel:from uri="direct:SomeTestRoute" />

<camel:log logName="MessageSenderToJMSQueue" loggingLevel="INFO"
message="Entered in MessageSenderToJMSQueue : ${body}" />

<camel:removeHeaders pattern="*" />

<camel:to uri="activemq:queue:test-queue" />
</camel:route>

<!-- Route which receive message from the test-queue with name queue-name -->

<camel:route id="MessageReceiverFromJMSQueue">
<camel:from uri="activemq:queue:test-queue" />

<camel:log logName="MessageReceiverFromJMSQueue" loggingLevel="INFO"
message="Entered in MessageReceiverFromJMSQueue : ${body}" />

<camel:to uri="direct:SomeTestRoute" />
</camel:route>

JMS Topic: Produce and consume messages using JMS Topic. Add below routes in your camel context file.

<!-- Route which sends message to the jms-topic with name test-topic -->

<camel:route id="MessageSenderToJMSTopic">
<camel:from uri="direct:SomeTestRoute" />

<camel:log logName="MessageSenderToJMSTopic" loggingLevel="INFO"
message="Entered in MessageSenderToJMSTopic : ${body}" />

<camel:removeHeaders pattern="*" />

<camel:to uri="activemq:queue:test-topic" />
</camel:route>

<!-- Route which receive message from the jms-topic with name test-topic -->

<camel:route id="MessageReceiverFromJMSTopic">
<camel:from uri="activemq:topic:test-topic" />

<camel:log logName="MessageReceiverFromJMSTopic" loggingLevel="INFO"
message="Entered in MessageReceiverFromJMSTopic : ${body}" />

<camel:to uri="direct:SomeTestRoute" />
</camel:route>

That's it. Now, build your application and run on Fuse Server. Your apps is ready to produce and consume messages from ActiveMQ using JMS API.

I hope you have enjoyed this camel riding. Please don't forget to give your feedback and suggestion to improve this article and of course my blog writing.

Thanks a lot for your time to read this blog.