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