Showing posts with label SOA. Show all posts
Showing posts with label SOA. Show all posts

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

Saturday, July 25, 2015

Apache Camel: Splitter Component And Aggregation EIP

Today, I'm going to explain about the Camel's Splitter component. I will also explain how and when to use this component. Here, I used Spring DSL to configure the splitter. So, let's start the camel riding.

The splitter component is based on Splitter EIP which allows you to split your incoming message into no. of smaller pieces and process them independently. It's considered as parallel processing of bulk messages which comes as a single bundled. The splitted message will be set as a body of message in newly created exchange which contains all the headers, properties of parent exchange. This component supports various data types including xml, json, csv, etc. This is about when to use this component.

There are various options available for this component which you can configure in spring dsl by setting respective attributes along with its value to make it more powerful route. Along with Splitter component I will also explain about the Aggregation EIP. The aggregation EIP is used to collect output from parallelly processed splitted messages. I think this is sufficient explanation for Splitter component. You can read from official Apache Camel website.



Now, Let's start the programming. I assume that you have created your project by using Maven.

<!-- Incoming XML -->
<Orders>
<Order>
<Header>...</Header>
<LineItems>
<LineItem>...</LineItem>
</LineItems>
<Footer>...</Footer>
</Order>
.
.
.
<Order>
<Header>...</Header>
<LineItems>
<LineItem>...</LineItem>
</LineItems>
<Footer>...</Footer>
</Order>
</Orders>

Now, Sping DSL for Splitter Copmonent,

<!-- This bean is used to collect the output from the splitted messages from splitter component -->
<bean id="aggregationBean" class="com.makhir.beans.AggregationStrategyBean" />

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

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

<camel:split strategyRef="aggregationBean" stopOnException="false">
<camel:xpath>//Orders/Order</camel:xpath>
<camel:to uri="direct:SplittedMessageProcessingRoute" />
</camel:split>

</camel:route>

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

<camel:log logName="SplittedMessageProcessingRoute" loggingLevel="INFO"
message="Entered in SplittedMessageProcessingRoute : ${body}" />
<!--
Add your business logic for validation, transformation, etc.
-->
<camel:to uri="direct:some-route"/>
</camel:route>

Now, I'm writing the aggregation class which is as per below,

package com.makhir.beans;

import org.apache.camel.Exchange;
import org.apache.camel.processor.aggregate.AggregationStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class AggregationStrategyBean implements AggregationStrategy {

private static Logger logger = LoggerFactory.getLogger(AggregationStrategyBean.class);

@Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {

try {
if (oldExchange == null || oldExchange.getIn() == null
|| oldExchange.getIn().getBody() == null
|| oldExchange.getIn().getBody(String.class) == null) {
checkAndProcessExchange(newExchange);
return newExchange;
} else if (newExchange == null || newExchange.getIn() == null
|| newExchange.getIn().getBody() == null
|| newExchange.getIn().getBody(String.class) == null) {
return oldExchange;
}
//Add your business logic for capturing the information from the splitted message(newExchange)
//and set it into parent message(oldExchange)

} catch (Exception e) {
logger.error("There was a problem while aggregating the data, error message " + e.getMessage());
}
return oldExchange;
}
}

That's it. You can try this by adding above routes in your camel context as per your requirement.

I hope you have enjoyed this camel ride.

Reference: Apache Camel

Thursday, October 18, 2012

ServiceMix ESB: Http Connector Component

HttpConnector in ServiceMix is very useful component.

Now, i am going  to show you about how to make an HttpConnector in ServiceMix enabled application.

There is nothing to do much more to create this component.

You should need to follow below steps and enjoy with facilities provided by the HttpConnector.

First of all you have to more specific and clarity with  your requirement and decide whether this component is useful or not.

Steps to configure the in-built component of the ServiceMix.

Step : 1 Servlet entry in web.xml
Here, you have to make an entry for your HttpConnector component.
Below is the code snippet for web.xml,
      <servlet>
        <servlet-name>extreme</servlet-name>
        <servlet-class>org.apache.servicemix.components.http.SpringBindingServlet</servlet-class>
         <init-param>
             <param-name>endpoint</param-name>
             <param-value>ExtremeHttpConnector</param-value>
         </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>extreme</servlet-name>
        <url-pattern>/extreme/*</url-pattern>
    </servlet-mapping>


After this we need to make an entry in ServiceMix configuration file where all other component resides.

Step : 2 Component Entry in configuration file
Now its time to add your component in config file where all other component resides.
Below is the code snippet,

<sm:activationSpec componentName="ExtremeHttpConnector" service="foo:AsiteDocumentReceiver" destinationService="foo:Your DestinationService">
                <sm:component>
                    <bean class="com.makhir.component.ExtremeHttpConnector" id="ExtremeHttpConnector">
                        <property name="defaultInOut" value="false"/>
                        <!--<property name="maxThreads" value="5"/> Number of instance of this components in jbi container-->
                    </bean>
                </sm:component>
            </sm:activationSpec>


Here, you can easily see that the componentName in config file is same as entry in web.xml.

Step : 3 HttpConnector java class
Now its time to do some coding for our component.

package com.makhir.component;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;

import javax.jbi.JBIException;
import javax.jbi.messaging.InOnly;
import javax.jbi.messaging.MessageExchangeFactory;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;
import javax.jbi.servicedesc.ServiceEndpoint;
import javax.resource.spi.work.Work;
import javax.resource.spi.work.WorkException;
import javax.resource.spi.work.WorkManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.servicemix.components.http.HttpConnector;
import org.apache.servicemix.components.util.CopyTransformer;
import org.apache.servicemix.jbi.framework.ComponentContextImpl;
import org.dom4j.Document;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


/**
 * This class handles the coming request for different type of documents publishing and processed
 * and pass to the relevant jbi component for further processing. This class uses some properties
 * file with respect to incoming document via http request for deciding the buyer-supplier integration.
 * @author Ashish Mishra 
 * @since 28-09-2012
 */
public class ExtremeHttpConnector extends HttpConnector{
    private boolean defaultInOut;
    private WorkManager workManager;
   
    public void setDefaultInOut(boolean defaultInOut) {
        this.defaultInOut = defaultInOut;
    }
   
    public boolean getDefaultInOut() {
        return defaultInOut;
    }
   
    public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, JBIException {
        processInOut(request, response);
    }
   
    public void processInOnly(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException, JBIException {
        try {
            // Do some logic here to process the incoming request

           processDocuments(file, request, response);
        } catch (ExtremeGenericException e) {
            return;
        } catch (Exception e) {
            return;
        }
    }
   
    public void processInOut(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException, JBIException {
        try {
        //  
        } catch (Exception e) {
           return;
        }
}
    /**
     * This method process the incoming documents and publish it against respective integration flow.
     *
     * */
    private boolean processDocuments(File[] files, HttpServletRequest request) throws WorkException, Exception {
        try {
            ComponentContextImpl contextImpl = (ComponentContextImpl) getContext();
            workManager = contextImpl.getWorkManager();
            HashMap<String, String> headerElements = ExtremeHttpHelper.getRequestHeaders(request);
            Map cgiMap = ExtremeHttpHelper.getCGIParameters(request);
            for (int index = 0; index < documentList.size(); index ++) {
                HashMap<String, Object> argMap = new HashMap<String, Object>();
                
argMap.put("headers", headerElements.clone());
                
argMap.put("cgiMap", ((HashMap)cgiMap).clone());
                
argMap.put("document", files[i]);
                asignToWorkmanager(
argMap);
            }
            return true;
        } catch (WorkException e) {
            throw e;
        } catch (Exception e) {
            throw e;
        }
    }
    /**
     * This method will create a separate thread for multiple document processing
     * */
    private void asignToWorkmanager(final Map<String, Object> paramMap) throws WorkException, Exception{
        try {
            workManager.scheduleWork(new Work() {
                @Override
                public void run() {
                    try {
                        processDocument(paramMap);
                    } catch (Exception e) {
                        return;
                    }
                }
                @Override
                public void release() {
                    // TODO Auto-generated method stub
                }
            });
        } catch (WorkException e) {
            throw e;
        } catch (Exception e) {
            throw e;
        }
    }
   
    private boolean processDocument(File file, HttpServletRequest request, HttpServletResponse response) throws Exception{
        String host = request.getRemoteHost();
        NormalizedMessage inMessage = null;
        InOnly exchange = null;
        try {
            Document xmlDocument =  null; // Add code to convert xml doc from the file
            MessageExchangeFactory factory = getExchangeFactory();
            exchange = factory.createInOnlyExchange();
            inMessage = exchange.createMessage();
            getMarshaler().toNMS(exchange, inMessage, request);
            exchange.setInMessage(inMessage);
            // Need to add some code for customizing the proccess flow of your document
            getDeliveryChannel().send(exchange);

// control handover to destination service as we configured for this component
             return true;
        }  catch (IOException e) {
            if(exchange != null)
                fail(exchange, e);
        } catch (MessagingException e) {
            if(exchange != null)
                fail(exchange, e);
        }catch (Exception e) {
            if(exchange != null)
                fail(exchange, e);
        }
        return true;
    }


private void processDocument(Map<String, Object> paramMap) throws Exception{
       NormalizedMessage inMessage = null;
        InOnly exchange = null;
        try {
            Document xmlDocument =  null; // Add code to convert xml doc from the file
            MessageExchangeFactory factory = getExchangeFactory();
            exchange = factory.createInOnlyExchange();
            inMessage = exchange.createMessage();
            getMarshaler().toNMS(exchange, inMessage, request);
            exchange.setInMessage(inMessage);
            // Need to add some code for customizing the proccess flow of your document
            getDeliveryChannel().send(exchange);

// control handover to destination service as we configured for this component
             return true;
        }  catch (IOException e) {
            if(exchange != null)
                fail(exchange, e);
        } catch (MessagingException e) {
            if(exchange != null)
                fail(exchange, e);
        }catch (Exception e) {
            if(exchange != null)
                fail(exchange, e);
        }
        return true;
    }

}
----------------------------------------------------------

Thats it.
Now your control handover to destination service as we configured for this component.

Now to  execute this component you should make an http call to this http-connector  with your application url.


For example, http://localhost:8080/makhir/extreme?action=document

Here,  /extreme is for your component which you mapped in web.xml.

Well done........
 
Great works by you....

Enjoy ServiceMix as an ESB...   

If any queries or questions, please update.

Thanks,
Ashish Mishra