Prerequisites
- Basic understanding of a web application (jsp, HTML form).
- Familiar with using IBM Integration Designer.
- Basic understanding of SCA applications (Creating Different components like Import, Export, Java Component)
Steps to Create a Working SCA HTTP Module
- Open the Integration designer and click on New-> mediation Module, a pop will appear asking to give the details of name of module.
To create Business object, Right Click -> New -> Business Object
Create an operation in the interface getFile and add the Request & Response Object created earlier to its input & output.
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;
}
************************************************************************************************************************************************
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):
- setDataObject(...)
- setHeaders(...)
- setControlParameters(...)
- setBusinessException(...)
- convertToNativeData()
- getControlParameters()
- getHeaders()
- write(...)
- Inbound processing (Native format to DataObject):
- setControlParameters(...)
- setHeaders(...)
- convertFromNativeData(...)
- isBusinessException()
- getDataObject()
- getControlParameters()
- getHeaders()
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 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.
Accept-Ranges bytes
Content-Disposition attachment; filename=Download_Pdf.pdf
Refer the figure below.
EndPoint URL - HTTPBinding_PIWeb/EXP_GetFileToDownload/getFile
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 :-)