Showing posts with label java. Show all posts
Showing posts with label java. 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

Wednesday, January 29, 2014

DOM4J: Remove duplicate xml elements from xml

Today i will explain about handling duplicate xml elements of xml.

I think you are little bit aware with DOM4J API from Apache Foundation.

DOM4J API basically is for playing with XML. Sometime your facing the issue that how to get distinct element list from the given xml. To achive this we iterate whole document and get required list. But same thing can be achive by given DOM4J API.

You need to have a latest copy of dom4j.jar. You can easily download it from Sourceforge

Here i will show you the practical example of the same.

//XML Document
<?xml version="1.0" encoding="UTF-8"?>
<document>
<element>
<id>1</id>
</element>
<element>
<id>1</id>
</element>
<element>
<id>2</id>
</element>
<element>
<id>3</id>
</element>
<element>
<id>2</id>
</element>
<element>
<id>6</id>
</element>
<element>
<id>5</id>
</element>
<element>
<id>3</id>
</element>
<element>
<id>4</id>
</element>
<element>
<id>4</id>
</element>
</document>

Now create one class file and add below code snippet in your class
String xmlDoc = ""; //Add code which reads the xml input file from your file location

//Creating org.dom4j.Document objet from xml content
Document document = DocumentHelper.parseText(xmlDoc);

//Now creating distinct list from the created xml ducument with below code snippet

List<Node> nodes = document.selectNodes("//document/element", "id", true);

/*
* XPath for distinct element : "//document/element"
* Element name on which nodes will be compare: "id"
* Boolean flag which indicates to remove duplicate nodes or not.
**/

Wednesday, February 27, 2013

DWR Integration Step By Step

Brief introduction of DWR
The DWR (Direct Web Remoting) project is an open source solution under the Apache license for the developer who wants to use AJAX and XMLHttpRequest in an easy way. It has a set of JavaScript functions that remove the complexity from calling methods in a Java object running on the application server from the HTML page. It handles parameters of different types and helps keep the HTML code readable.

DWR is not intrusive to one's design, as it does not force any sort of inheritance architecture for objects to be exposed. It fits well in any application that runs in a servlet framework. For the less DHTML-experienced developers, DWR also provides a JavaScript library to help with frequently used DHTML tasks, like populating tables, filling select boxes with items, and changing the content of HTML elements such as and.

The DWR Website is comprehensive and has a fair amount of documentation, which has served as a foundation for this article. Some examples are provided to demonstrate how DWR can be used and what can be accomplished with the library.
Reference: Java World

I am going to show you about how to integrate DWR framework in your running J2EE application. Below are the steps to configure DWR framework.

Step 1: Download required files
For integrating DWR in your application, you need some supported files. You can easily find these files on official page of DWR.
http://directwebremoting.org/dwr/index.html

You need to download below files,
1) dwr.jar [http://directwebremoting.org/dwr/downloads/index.html] [deploy in your respective WEB-INF/lib dir]
2) commons-logging.jar [deploy in your respective WEB-INF/lib dir]
3) util.js [deploy in your respective folder where your jsp and js files resides]
4) engine.js [deploy in your respective folder where your jsp and js files resides]

Step 2: Configuration in your web application
We need to create dwr.xml file where your DWR related configuration and put this file in dir where your web.xml of your application reside.
I am showing the structure of the dwr.xml.
// DWR XML Content

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
<dwr>
<!-- init is only needed if you are extending DWR
<init>
<creator id="..." class="..." />
<converter id="..." class="..." />
</init> -->
<!-- without allow, DWR isn't allowed to do anything -->
<allow>
<filter class="com.makhir.filters.DWRFilter" /><!-- Your DWR filter here which manage the request/response to DWR servlet -->
<create creator="new" javascript="DWRInvoker"><!-- Your DWR Servlet class which handles the actual request and response -->
<param name="class" value="com.makhir.servlets.DWRInvoker"/>
</create>
<convert converter="bean" match="com.makhir.vo.UserRegisterVO" /> <!-- POJO entry for transferring along network if any-->
</allow>
<!-- you may need to tell DWR about method signatures
<signatures>
...
</signatures> -->

</dwr>

Now make an entry for dwr servlet in web.xml for URL mapping as below,
// web.xml entry
<servlet>
<servlet-name>dwr-starter</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
  </init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-starter</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
Thats it as point of configuration.

Step 3: Code changes for Server side management
A) Create one filter with name DWRFilter whose entry is already available in dwr.xml with name DWRFilter
Note: We need not make this filter entry in our web.xml as we do traditionally
Below is the code snippet of for the filter,

//DWRFilter.java
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.directwebremoting.AjaxFilter;
import org.directwebremoting.AjaxFilterChain;

public class DWRFilter implements AjaxFilter{
private static Log logger = LogFactory.getLog(DWRFilter.class);
@Override
public Object doFilter(Object object, Method method, Object[] params, AjaxFilterChain filterChain) throws Exception {
logger.debug("Enter : Entering into DWRFilter");
// TODO: Add code for some filteration on methods and params which are interchange between server and client
logger.debug("Exit : Entering into DWRFilter");
return filterChain.doFilter(object, method, params);
}
}

B) Create class for which is going to responsible for handling your reqeust of dwr call from the client
Here i made a class with name DWRInvoker.java as its entry already available in dwr.xml
Below is the code snippet of for the filter,

//DWRInvoker.java
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.makhir.vo.UserRegisterVO;

public class DWRInvoker {
private static Log logger = LogFactory.getLog(DWRInvoker.class);
public DWRInvoker(){} // Default Constructor
public Object getUserInfo(String userId){
logger.debug("Enter : getUserInfo()");
UserRegisterVO registerVO = new UserRegisterVO(); //UserRegisterVO which is going to transfer on network.Its entry available in dwr.xml
registerVO.setUserName("Ashish Mishra");
registerVO.setUserId(userId);
registerVO.setDepartment("Development");
logger.debug("Exit : getUserInfo()");
return registerVO;
}
}

C) Create POJO class which is also your value object. Here i have created with name UserRegistrationVO.java.
Make an entry in dwr.xml in convert element.

Step 4: Code changes for client side management
Now its time make some changes on client side.
Here we need to create jsp files in which you want to manage your interaction with client and server with help of DWR call.
A) Download engine.js file from official DWR home page and depoly it in your dir where your jsp resides
B) Download util.js file from official DWR home page and depoly it in your dir where your jsp resides
C) Creating DWRInvoker.js in your application where your jsp and scripting files resides

Below is script snippet for your reference,
  //DWRInvoker.js

if (typeof dwr == 'undefined' || dwr.engine == undefined) throw new Error('You must include DWR engine before including this file');
(function() {
 if (dwr.engine._getObject("DWRInvoker") == undefined) {
var p;

p = {};
p._path = '/extreme/dwr';

/**
* @param {class java.awt.image.BufferedImage} p0 a param
* @param {class java.lang.String} p1 a param
* @param {class java.lang.String} p2 a param
* @param {function|Object} callback callback function or options object
*/
p.getUserInfo = function(p0, callback) {
 return dwr.engine._execute(p._path, 'DWRInvoker', 'getUserInfo', arguments);
};

dwr.engine._setObject("DWRInvoker", p);
 }
})();
/**
function DWRInvoker(){}
DWRInvoker.getUserInfo = function(p0,callback){
DWREngine._execute('/extreme/dwr','DWRInvoker','getUserInfo',p0,callback);
}
*/
D) Create your JSP page from where actual DWR calling will happen
  Here, i my case i have created the jsp file for your reference with name profilePage.jsp which load the profile details.
  DWR call will made by the client when profilePage.jsp is load and fetch specific user profile data from server and display it onto client
  browser without refreshing the page.
  You can make DWR call through any of events supported by the HTML component.
  Below is code snippet of the jsp file.
 
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Extreme Application</title>
<script type="text/javascript" src="engine.js"> </script> <%-- engine.js which should always be first  script file to be included [Mandatory] --%>
<script type="text/javascript" src="DWRInvoker.js"> </script> <%-- DWRInvoker.js needs to be included [Mandatory]--%>
<script type="text/javascript" src="util.js"> </script> <%-- util.js needs to be included for enhance the feature provided by DWR[Optional] --%>
<script type="text/javascript">
function loadProfile(){
dwr.util.useLoadingImage('images/ajax-loader.gif'); <%-- Progress image for showing the progress of dwr call on client side  --%>
DWRInvoker.getUserInfo(<%=userid%>, getinfo); <%-- Actual DWR call to get user's profile data from the server  --%>
}
function getinfo(data){ <%-- scripting method which handles the server response from DWR call--%>
document.getElementById("txtUserName").value = data.userName;
document.getElementById("txtDept").value = data.department;
document.getElementById("txtCity").value = data.city;
}
</script>
</head>
<body onload="loadProfile();">
<form action="#" method="post" name="updateFrom" id="updateFrom" enctype="multipart/form-data">
<table align="left" id="regisTable" style="border-color: gray;">
<tr>
<td class="td">Name</td>
<td class="td">:</td>
<td class="td"><input type="text" name="txtUserName" id="txtUserName" value="''"/></td>
</tr>
<tr>
<td class="td">Department</td>
<td class="td">:</td>
<td class="td"><input type="text" name="txtDept" id="txtDept" value="''"/></td>
</tr>
<tr>
<td class="td">City</td>
<td class="td">:</td>
<td class="td"><input type="text" name="txtCity" id="txtCity" value="''" /></td>
</tr>
</table>
</form>
</body>
</html>

I think i might have covered all those things which required to configure DWR in J2EE application.

Regards,
Ashish Mishra

Wednesday, September 26, 2012

ServiceMix ESB: Quartz Integration


ServiceMix: Enterprise Service Bus.

Here, I am showing that how you integrate the Quartz component with Apache ServiceMix.

I assume that you some knowledge about ServiceMix and its architecture. I give you higher over view of ServiceMix.

Apache ServiceMix is a runtime container for service-oriented architecture components, web services or legacy system connectivity services. It is one of the most mature, open-source implementations of an enterprise service bus and an Apache top-level project.

For more, you can visit on http://servicemix.apache.org









I am not going to in detail of ServiceMix and its component and its working style. You can easily refer from various blogs and websites.

Let’s start implementing the Quartz component your existing running application which uses Apache ServiceMix.

First download the quartz jar file from its official site. Here i have used quartz-1.5.2.jar and add this jar to your lib folder.

Please, add below entry into say servicemix.xml [e.g. config file where you have specified all your component in spring’s bean like passion],

--------------------------------------------
<sm:activationSpec componentName="QuartzSchedular" service="foo:QuartzSchedular"  destinationService="foo:extremeEmailNotifier">
<sm:component>
<bean class="com.makhir.ExtremeQaurtzSchedular" id="QuartzSchedular">
<property name="marshaler">
<bean class="org.apache.servicemix.components.quartz.DefaultQuartzMarshaler" />
</property>
<property name="triggers">
<map>
<entry>
<key>
<bean class="org.quartz.SimpleTrigger">
<property name="repeatInterval" value="30000" /><!--Time in which your component will start its execution-->
<property name="repeatCount" value="-1" />
</bean>
</key>
<bean class="com.makhir.quartz.ExtremeQuartzJob">
<property name="name" value="makhirJob" />
<property name="group" value="ServiceMix" />
</bean>
</entry>
</map>
</property>
</bean>
</sm:component>
</sm:activationSpec>
----------------------------------------------------


Now, it’s time create a full component which is our primary goal.
Below is sample code which you needs to make your component into a working condition,
-------------
public class ExtremeQuartzSchedular extends QuartzComponent{
private final Log log = LogFactory.getLog(ExtremeQuartzSchedular.class);
private Map triggers;
private SchedulerFactory factory;
private Scheduler scheduler;
private WorkManager workManager = null;
@Override
public void setScheduler(Scheduler scheduler) {
   this.scheduler = scheduler;
}*/
@Override
public void setMarshaler(QuartzMarshaler marshaler) {
super.setMarshaler(marshaler);
}
@SuppressWarnings("rawtypes")
@Override
public void onJobExecute(JobExecutionContext context) throws JobExecutionException {
log.debug("Enter : onJobExecute");
try {
ComponentContextImpl contextImpl = (ComponentContextImpl) getContext();
workManager = contextImpl.getWorkManager();
File pollDirectory = new File("C:\\makhir\\workspace\\XJavaTest\\xmls");
File[] files = pollDirectory.listFiles();
for(int index = 0; index < files.length; index ++){
initializeJob(files[index]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*public Map getTriggers(){
return this.triggers;
}
public void setTriggers(Map triggers){
this.triggers = triggers;
}*/
protected void initializeJob(final File processFile){
log.debug("Enter : initializeJob");
log.debug("Proccessed file name : " + processFile.getName());
try {
workManager.scheduleWork(new Work() {
@Override
public void run() {
try {
doJob(processFile);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void release() {
}
});
// this code is for handling the work to be handled via workmanager with additional feature listener
/*workManager.scheduleWork(new Work() {
@Override
public void run() {
try {
doJob(processFile);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void release() {
}
}, 1000, new ExecutionContext(), new ExtremeWorkListner());*/ 
// 1000(1 sec) miliseconds within this time work must be started otherwise work will be rejected with rejected exception
} catch (WorkException e) {
log.error("WorkException :  Error while initialzing the job, " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
log.error("Exception :  Error while initialzing the job, " + e.getMessage());
}
log.debug("Exit : initializeJob");
}
protected void doJob(File file) throws IOException{
log.debug("Enter : doJob");
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
MessageExchangeFactory exchanageFactory = getExchangeFactory();
InOut outMessage = exchanageFactory.createInOutExchange();
NormalizedMessage message = outMessage.createMessage();
message.setProperty("toEmailid", new String("abc@xyz.com"));
message.setProperty("fromEmailid", new String("notifications@xyz.com"));
message.setProperty("emailSubject", new String("How are you?"));
message.setProperty("bodyContent", convertStreamtoString(inputStream)));
outMessage.setInMessage(message);
send(outMessage);
} catch (MessagingException e) {
log.error("MessagingException : There was a problem exchanging the message");
e.printStackTrace();
} catch (JBIException e) {
log.error("JBIException : There was a problem exchanging the message");
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace(); 
}
finally{
try {
if (inputStream != null)
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
log.debug("Exit : doJob");
}
@SuppressWarnings("unused")
private String convertStreamtoString(InputStream stream) throws IOException{
log.debug("Enter : convertStreamtoString");
StringBuffer buffer = new StringBuffer();
   byte[] b = new byte[4096];
   for (int n; (n = stream.read(b)) != -1;) {
     buffer.append(new String(b, 0, n));
   }
   String messageContent = buffer.toString();
   log.debug("Converted input stream to string : " + messageContent);
   log.debug("Exit : convertStreamtoString");
return messageContent;
}
}



--------------------------

Now I will describe you how this component works.

After doing all this stuffs, when you start your ServiceMix integrated server, the ExtremeQuartzSchedular executes with all the initialization done by ServiceMix itself.

Here, I have use this component for looking some directory from where files will be picked up and email their content to someone.

The NormalizedMessage will be sent to the destinationService as defined in config file.

Here, this message will send to extremeEmailNotifier.

That's it.

I will explain later on about extremeEmailNotifier which is basically for sending email.

Enjoy with ServiceMix.

Feedback and questions are welcome.

Regards,
Ashish Mishra (makhir)