In this Example we are going to develop a SCA application that gets the input as a location of a pdf file. read the PDF and returns the byte array. This application will be exposed via HTTP Binding so that it can be integrated with a web application.

Prerequisites
  1. Basic understanding of a web application (jsp, HTML form).
  2. Familiar with using IBM Integration Designer.
  3. Basic understanding of SCA applications (Creating Different components like Import, Export, Java Component)


Steps to Create a Working SCA HTTP Module
  1. Open the Integration designer and click on New-> mediation Module, a pop will appear asking to give the details of name of module.

2. Create two Business Object for our interface. Request Object and Response object. request Object will contain a string variable for storing the location of file. response Object will have a pdfBytes variable of base64binary type to store the read file bytes.

To create Business object, Right Click -> New -> Business Object
3. Create an Interface right Click -> New -> Interface.
     Create an operation in the interface getFile and add the Request & Response Object created earlier to its input &      output.
4. Create a Java component and attach the Interface to that component. create an export and link it to the Java Component. generate the Binding for for Export component (Http Binding) and Implement the java component.
At this point we have build the basic structure of our Module. from Now on we will proceed Step By Step with explanation as to why that step is required.

The first thing that need to be done is Converting HTTP Post data in to Request Business Object. For that We need either a datahandler or databinding. we will make use of both these two illustrate their functions.

We will create a data handler that will process the incoming request. i.e it will convert HTTP Post data in to Input Business Object.
A data binding will also be created to process the outgoing response. i.e converting response object in to HTTP native data.

5. Create a data handler
To create a data handler yo need to create a class that implements DataHandler Interface.
    commonj.connector.runtime.DataHandler
After doing that we need to Implement the 3 Abstract method of DataHandler Interface.

a. transform() - used to convert the Native data of protocol to DataObject for Incoming Request.
b. transformInto
() - used to convert the DataObject in to Native Data for outgoing response.
c. setBindingContext() - To bind the context.

We are more concerned about transform method because we are using this datahandler for incoming request , for outgoing response we are going to create a different databinding.

transform(Object source, Class arg1, Object agr2) method has three parameters
.

basically we have to convert the source in to Our Request DataObject
.

Source in this case will be InputStream (as it is HTTP Call we are processing.)

Input Stream contains all the parameters in HTTP Form body.

Lets create a class CustomHTTPDataHandler and implements DataHandler interface in it.

************************************************************************************************************************************************   
package com.pi.httpbinding;
import java.io.IOException;
import commonj.sdo.DataObject;
import com.ibm.websphere.sca.ServiceManager;
import java.util.Map;
import java.io.InputStream;
import commonj.connector.runtime.DataHandler;
import commonj.connector.runtime.DataHandlerException;

public class CustomHTTPDataHandler implements DataHandler {

private static final long serialVersionUID = 1L;

public Object transform(Object source, Class arg1, Object arg2)
    throws DataHandlerException {

            int bufferSize = 2000 * 4;
            String inputStr = null;
            if (source instanceof InputStream) {
            InputStream is = (InputStream)source;
            try {
                is =(InputStream)source;
                byte[] inputs = new byte[is.available()];
                is.read(inputs);
                inputStr = new String(inputs);
                System.out.println("InputStream-"+inputStr);
                is.reset();
                String[] param=inputStr.split("&");
                for(int i=0;i<param.length;i++)
                    {
                    String decoded = java.net.URLDecoder.decode(param[i], "UTF-8");
                    if(decoded.startsWith("pdf="))
                        {
                        String path =decoded.substring(4);
                        com.ibm.websphere.bo.BOFactory boFactory =            (com.ibm.websphere.bo.BOFactory)                                                       ServiceManager.INSTANCE.locateService("com/ibm/websphere/bo/BOFactory");
                         DataObject BO = boFactory.create("http://HTTPBinding_PI", "RequestObj");
                         BO.setString("pdfLocation",path);
                        return (Object)BO;
                    }  
                }
            } catch (IOException e) {
        e.printStackTrace();
       
    }
   
}

else{
        throw (new DataHandlerException("Input must be of InputStream type"));
    }
return null;
}


    public void setBindingContext(Map context) {
           
    }


public void transformInto(Object source, Object target, Object options)
            throws DataHandlerException{

//Not Implemented because we will Implement the Data Binding to process the response.

}



}

************************************************************************************************************************************************

Now with this class your Input data from HTML form will be converted in to RequestObj & will be passed on to SJ_GetFileToDownload in form of Business Object. Ofcourse you need to configure this class to the export component to make it work, that we will do a little later.

6. Implement the getFile function.


Now we will Implement the operation getFile in Sj_GetFileToDownloadImpl class.

************************************************************************************************************************************************
public DataObject getFile(DataObject input1) {
        try {
            com.ibm.websphere.bo.BOFactory boFactory = (com.ibm.websphere.bo.BOFactory)                    ServiceManager.INSTANCE.locateService("com/ibm/websphere/bo/BOFactory");
            DataObject response = boFactory.create("http://HTTPBinding_PI",
                    "ResponseObj");
            String location = input1.getString("pdfLocation");
            System.out.println(location);
            byte[] pdfBytes = null;
            URL u = new URL(location);
            URLConnection uc = u.openConnection();

            String contentType = uc.getContentType();
            int contentLength = uc.getContentLength();
            if (contentType.startsWith("text/") || contentLength == -1) {
                throw new IOException("This is not a binary file.");
            }
            InputStream raw = uc.getInputStream();
            InputStream in = new BufferedInputStream(raw);
            pdfBytes = new byte[contentLength];
            int bytesRead = 0;
            int offset = 0;
            while (offset < contentLength) {
                bytesRead = in.read(pdfBytes, offset, pdfBytes.length - offset);
                if (bytesRead == -1)
                    break;
                offset += bytesRead;
            }
            in.close();
            raw.close();
            if (offset != contentLength) {
                throw new IOException("Only read " + offset
                        + " bytes; Expected " + contentLength + " bytes");
            }
            response.setBytes("pdfBytes", pdfBytes);
            return response;

        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("Returned");
        return null;
    }

************************************************************************************************************************************************
At this stage we have developed our data handler for input processing & implemented the java component function that will read a pdf file from a location and convert it in to bytes array and set in the ResponseObj and return it back to Export component.


7. Create a Data Binding for converting the response stored in Business Object in to HTTPOutput Straem to process by Browser.



Create a class CustomHTTPDataBinding that implements
HTTPStreamDataBinding Interface.


The data binding should have four private properties:
  • private DataObject pDataObject
  • private HTTPControl pCtrl
  • private HTTPHeaders pHeaders
  • private yourNativeDataType nativeData



The HTTP binding will invoke the customized data binding in the following order:
  • Outbound processing (DataObject to Native format):
    1. setDataObject(...)
    2. setHeaders(...)
    3. setControlParameters(...)
    4. setBusinessException(...)
    5. convertToNativeData()
    6. getControlParameters()
    7. getHeaders()
    8. write(...)
  • Inbound processing (Native format to DataObject):
    1. setControlParameters(...)
    2. setHeaders(...)
    3. convertFromNativeData(...)
    4. isBusinessException()
    5. getDataObject()
    6. getControlParameters()
    7. getHeaders()
As we have already dealt the Inbound processing via our DataHandler, We will concentrate on implementing the methods for Outbound Processing.

lets have a look on these function and their purpose.


setDataObject(..) - This will set the data object response from java component (SJ_GetFileToDownload)

setHeaders(...) - Will set the Headers for HTTP call.

setControlParameters(...)  - Will set the control parameters for HTTP Protocol.

setBusinessException(...) - Set Exception if happend during processing. Not required for our case.

convertToNativeData()  - it converts the DataObject in to the Native Data by calling specialised function realConvertWorkFromSDOToNativeData()

getControlParameters() - get the control parameters set before writing in the output stream

getHeaders() - get the set headers before writing in the output stream

write(...)  write the byte content in to stream.



************************************************************************************************************************************************

package com.pi.httpbinding;

import java.io.IOException;
import java.util.Arrays;
import com.ibm.websphere.http.data.bindings.HTTPStreamDataBinding;
import com.ibm.websphere.http.data.streams.HTTPInputStream;
import com.ibm.websphere.http.data.streams.HTTPOutputStream;
import com.ibm.websphere.http.headers.HTTPControl;
import com.ibm.websphere.http.headers.HTTPHeaders;
import com.ibm.websphere.http.headers.HTTPHeader;
import com.ibm.websphere.http.headers.HeadersFactory;
import commonj.connector.runtime.DataBindingException;
import commonj.sdo.DataObject;

public class CustomHTTPDataBinding implements HTTPStreamDataBinding {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    DataObject pDataObject;
    HTTPControl pCtrl;
    HTTPHeaders pHeaders;
    byte[] nativeData;

        public void setDataObject(DataObject dataObject)
                throws DataBindingException {
            System.out.println("Call Set DataObject");
            pDataObject = dataObject;

        }

        public void setControlParameters(HTTPControl arg0) {
            System.out.println("Call Set Control Parameters");
            this.pCtrl = arg0;
        }

        public void setHeaders(HTTPHeaders arg0) {
            System.out.println("Call Set Headers");
            this.pHeaders = arg0;
        }

        /*
         * Add http header "IsBusinessException" in pHeaders. Two steps: 1.Remove
         * all the header with name IsBusinessException (case-insensitive) first.
         * This is to make sure only one header is present. 2.Add the new header
         * "IsBusinessException"
         */
        public void setBusinessException(boolean isBusinessException) {
            System.out.println("Call Set Business Exception");
            }

        public HTTPControl getControlParameters() {
            System.out.println("Call get CP");
            return pCtrl;
        }

        public HTTPHeaders getHeaders() {
            System.out.println("Call get headers");
            return pHeaders;
        }

        public DataObject getDataObject() throws DataBindingException {
            System.out.println("Call get DataObject");
            return pDataObject;
        }

        /*
         * Get header "IsBusinessException" from pHeaders, return its boolean value
         */
        public boolean isBusinessException() {
            System.out.println("Is Busn Excep");
            String headerValue = "false";//getHeaderValue(pHeaders, "IsBusinessException");
            boolean result = Boolean.parseBoolean(headerValue);
            return result;
        }

        public void convertToNativeData() throws DataBindingException {
            System.out.println("Call To Native Data");
            DataObject dataObject = getDataObject();
            this.nativeData = realConvertWorkFromSDOToNativeData(dataObject);
        }

        public void convertFromNativeData(HTTPInputStream arg0) {
            // Customer-developed method to
            // Read data from HTTPInputStream
            // Convert it to DataObject
            System.out.println("Call To BO Convert");
            DataObject dataobject = realConvertWorkFromNativeDataToSDO(arg0);
            try{
                setDataObject(dataobject);
            }catch(Exception e){
                e.printStackTrace();
            }
            
        }

    public void write(HTTPOutputStream output) throws IOException {
        System.out.println("Call Write");
        if (nativeData != null) {

            output.write(nativeData);

        }

    }
        public byte[] realConvertWorkFromSDOToNativeData(DataObject dataObject)
        {
            System.out.println("Call realConvertWorkFromSDOToNativeData");
            byte[] byteArray=null;
            byteArray=dataObject.getBytes("pdfBytes");//getPDFBytes();
                  //target =baos;
            
            return byteArray;
        }
        public DataObject realConvertWorkFromNativeDataToSDO(HTTPInputStream arg0)
        {
            System.out.println("Call realConvertWorkFromNativeDataToSDO");
            
            return null;
        }
        

}

************************************************************************************************************************************************


Now we have all the code ready for our SCA Application.

We just need to link all these components to make it work properly.


8. Configure the HTTP Export Component.


Click the export Component EXP_GetFileToDownload. and go to the properties tab of it.

select Binding tab in it.

Select Default Data format.(default It will be UTF8XMLDataHandler) Select your custom data handler developed and add it in registry.

Go To Advanced Configurations and in HTTP Header tab select the Transfer Encoding from identity to Chunked(as we are sending bytes for file to be downloaded)
Go to HTTP Method tab and change the method type from GET to POST.

Go To Method Binding Tab -> Data Serialization and select Input Data Format to CustomHTTPDataHandler & Output Data format as CustomHTTPDataBinding class that we have developed.

In
Method Binding Tab go to HTTPHeaders and change the Transfer Encoding to Chunked.
In HTTP Method tabs Change the method from GET to POST.

In Method Binding Tab go to HTTP Headers and add the following header
Accept-Ranges bytes
Content-Disposition attachment; filename=Download_Pdf.pdf

Refer the figure below.
Go to summary tab and make a note of Endpoint URL. this is the URL we will call from a consumer to use this service

EndPoint URL - HTTPBinding_PIWeb/EXP_GetFileToDownload/getFile

Save the Project, Clean it and build it.We are done with all the required components and their configuration for our Service provider Module.To test it we need a service Consumer.
In this case our service consumer will be a simple web application having only one jsp which will call this HTTP SCA Application.


8. Creating a simple web application to call the HTTP SCA Application.

a. Right click on the project explore view. click New -> Project

Search for Dynamic Web Project.

Create a Dynamic Web Project and gie the Project name (HTTP_WebApp_Consumer)

b. Right click on Web Content folder and Click New- > Jsp File

Create a Jsp page with some name (index.jsp)


C. Create a form in the body of JSP page.


d. Add the form inside the body.

Your jsp page will look like this

index.jsp

**********************************************************************************************************************************
<%@ page language="java" content
    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>Insert title here</title>
</head>
<body>
Sample Web App for Calling SCA Application Exposed via HTTP Binding
<form action="http://localhost:9080/HTTPBinding_PIWeb/EXP_GetFileToDownload/getFile" method="post">
<input name="pdf" value="file://///xx.xx.xx.xx/myfolder/abc.pdf"/>
<input name="Submit" value="submit">
</form>
</body>
</html>


*********************************************************************************************************************************
The red colored portion
is the path of your pdf file. where xx.xx.xx.xx denotes the machine ip. replace the path according to your pdf location.


Now we are ready to test our modules developed.

deploy both the SCA app as well as Web application in your Process Server.

Run the index.jsp and click the submit button in it.

You should be Getting a pdf to download if everything is working as expected. :)

Let me know in case you have a question.


Have a good day :-)


Chandrakant
12/9/2013 06:35:52 pm

Hi
I am developing a service which calls a Servlet. This service implemnent HTTP binding to invoke that servlet. This servlet only accept contentType of "application/x-www-form-urlencoded" . I have three element in my Business object which needs to be converted to Http request Body and looks like "paramOne=test1&ParamTwo=test2¶mThree=test3".

The service accept a SOAP call and needs to invoke a HTTP binding.

Please suggest.

Reply
Vishwash
12/11/2013 03:52:25 pm

Hi Chandrakant,

Calling the servlet via HTTP Binding will be in a same way. you need to use import component and configure the url for your servlet in import. DataBinding needs to be modified a little for calling this servlet with three parameter. Let me know if i made it clear to you, else i can put up a tutorial for it.

Reply
Cv
12/11/2013 06:06:44 pm

Vishwas,
Thanks for your reply. I was doing all good in sense implementing the Http binding and all configuration was good. I had issue in understanding the way to convert BusinessObject in Http Post Request data (url encoded) and what to use, either CustomData handler or CustomData Binding, for creating POST data as Url encoded.

This tutorial of yours really helped and answer was already there. Finally I wrote a Custom Data Binding which works for me. I created the same way you have done in your tutorial above.

Cv

Reply
Cv
12/11/2013 06:06:54 pm

Vishwas,
Thanks for your reply. I was doing all good in sense implementing the Http binding and all configuration was good. I had issue in understanding the way to convert BusinessObject in Http Post Request data (url encoded) and what to use, either CustomData handler or CustomData Binding, for creating POST data as Url encoded.

This tutorial of yours really helped and answer was already there. Finally I wrote a Custom Data Binding which works for me. I created the same way you have done in your tutorial above.

Cv

Reply
Chandrakant
12/11/2013 06:07:07 pm

Vishwas,
Thanks for your reply. I was doing all good in sense implementing the Http binding and all configuration was good. I had issue in understanding the way to convert BusinessObject in Http Post Request data (url encoded) and what to use, either CustomData handler or CustomData Binding, for creating POST data as Url encoded.

This tutorial of yours really helped and answer was already there. Finally I wrote a Custom Data Binding which works for me. I created the same way you have done in your tutorial above.

Cv

Reply
Vishwash
12/11/2013 08:11:59 pm

I am glad it helped you :-)

Jagadish
11/28/2016 10:54:55 am

Can you please share the sample of Custom Data binding which got worked for you

Reply



Leave a Reply.