Matter faced during integration project

Sunday, September 12, 2010

Connecting to Ariba with a Java API

To connect to Ariba, you use the Ariba Integration Toolkit. It consists of java libraries and batch scripts.
Using the batch script was uneasy for us, as it means we had to schedule 2 jobs: one to get or retrieve the files from Ariba and another job to process the file.

A much easier solution, was to call the Ariba java library straight away from our java code. To do that we had to dig into the batch file and decompile the java code.
Then to call the Ariba Java API, you simply add Ariba libraries to your classapth and you call the following code:

public class CallAriba {

public static void main(String[] args) {

String[] s = buildArg();

ariba.filetransferclient.Main.main(s);

}

private static String[] buildArg() {

String[] arguments = {

"get",

"-url",

"https://s1.ariba.com/Buyer/filedownload?realm=myCompanyRealm",

"-sharedSecret",

"myCompanySharedSecret",

"-downloadDir",

"C:/temp/ariba",

"-timestampFile",

"C:/temp/ariba/time.txt",

"-filePrefix",

"OK2Pay",

"-logFile",

"C:/temp/ariba/logs/log-test.log",

"-proxyHost",

"10.0.225.201",

"-proxyPort",

"8080",

"-unzipDirs",

"false",

"--",

"-event",

"Export Payment Requests"};

return arguments;

}

Wednesday, March 3, 2010

Sending SOAP request with JDK library



private static synchronized
String sendSOAPRequest(String soapMsg, String webserviceMethod, String soap_Endpoint) throws Exception {
try {
URL url = new URL(soap_Endpoint);
// setup HTTP Connecten to the service
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);

// create SOAP Request
connection.setUseCaches(false);
connection.setRequestProperty("Content-type", "text/xml; charset=iso-8859-1");
connection.setRequestProperty("SOAPAction", webserviceMethod);
System.out.println("SOAP-Endpoint: " + url);
System.out.println("SOAP-Action: " + webserviceMethod);

// send SOAP-Request
byte[] bytes = soapMsg.getBytes();
connection.setRequestProperty("Content-length", String.valueOf(bytes.length));
OutputStream out = connection.getOutputStream();
out.write(bytes);
out.close();

// read SOAP-response
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} catch (IOException e) {
if (connection.getResponseCode() == 500)
in = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
else
throw e;
}
// handle the SOAP response
StringBuffer in_buffer = new StringBuffer(8192);
String temp = "";
while ((temp = in.readLine()) != null) {
in_buffer.append(temp);
}
in.close();
return in_buffer.toString();
} catch (Exception e) {
System.out.println("!!! Exception: " + e);
throw e;
}
// return "";
}

Tuesday, February 16, 2010

BPEL and Oracle Siebel CRM On Demand

When integrating OCOD (aka Oracle Siebel CRM On Demand) using BPEL and Java application,
issues arise for:
1. keeping credentials session open with Oracle CRM On Demand because OCOD accept only 10 concurrent session + it is faster to re-use existing session
2. OCOD refuse 2 request to be made without 50ms between each requests
3. session need to be reset if OCOD server restart

An option is to add the session id to the end point of the partner link in the BPEL process.
Another option is to use java embedded code in BPEL and login and loggof to OCOD.

Those 2 options did not really fit with our requirements. Too slow, not scalable, dodgy to maintain, etc...

Our approach has been to use a proxy between our BPEL engine and OCOD.
So all partner link to OCOD from our BPEL process use this proxy as the end point for the partner link. Thus all calls from our application to OCOD is going through this proxy.

It consist of a Java web application deployed as a war file (11Kb) it manages:
- sessions
- authentication (so no password in clear text inside our BPEL process)
- the 50 ms wait that must exist between each request to OCOD

The code for this proxy is located here:

you can check it out like that:

# Non-members may check out a read-only working copy anonymously over HTTP.
svn checkout http://ocod-proxy.googlecode.com/svn/trunk/ ocod-proxy-read-only
The idea is to make it public so that anybody can use it and tell if he meets any issues.
Then tell me if you want to modify and enhance it. I would provide an access to the SVN repository.



Wednesday, November 25, 2009

Using OWSM and BPEL PM behind a proxy

We use OWSM and BPEL PM to consumme services outside our network.
Nothing to fancy so far, we had to modify the JVM settings and add the following parameter:

Dhttp.proxySet=true
Dhttp.proxyHost = proxy_server
Dhttp.proxyPort = listen_port
Dhttp.nonproxyHost = *localhost|*domain.com

in our case this was:
Dhttp.proxySet=true
Dhttp.proxyHost = www-proxy.outsourcing.com
Dhttp.proxyPort = 80
Dhttp.nonproxyHost = *outsourcing.com

Do not forget to add your localhost as non proxy.
The JVM settings can be accessed through the OC4 console or by editing the file

ORACLE_HOME/opmn/conf/opmn.xml

Then we add to consumme an https service and the add the settings:
Dhttps.proxySet=true
Dhttps.proxyHost = www-proxy.outsourcing.com
Dhttps.proxyPort = 80
Dhttps.nonproxyHost = *outsourcing.com

The case has to be exactly that and only a restart of the OC4J instance is not enough- You have to restart the JVM.
Also note that this cannot be changed without a restart.

Tuesday, October 20, 2009

Consuming Web Services with Jakarta Commons HttpClient

Consuming web services with Jakarta Commons HttpClient can be useful to reuse all the API provided by HttpClient.
The example below query a web service that requires HTTP authentication. We could also use that mechanism for NTLM or proxy authentication.
More generally, for all authentication made in the HTTP layer rather than the SOAP layer, HttpClient is a good candidate.

To run this code you need the library of HttpClient and HttpCore. I used version 4.0 and 4.0.1

you also need commons codec: I used version 1.4

To consume Web Services protected with NTLM (sic). You can refer to this page: http://www.luigidragone.com/networking/ntlm.html

So here's the code:


package org.apache.http.examples.client;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

/**
* A simple example that uses HttpClient to execute an HTTP request against a
* target site that requires user authentication.
*/
public class ClientAuthentication {

private static final String XML_DATA =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> "
+ "<soap:Body xmlns:ns1=\"http://xmlns.oracle.com/SensorBPEL\">" + "<ns1:SensorBPELProcessRequest><ns1:input>toto</ns1:input></ns1:SensorBPELProcessRequest>"
+ "</soap:Body></soap:Envelope>";

public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();

httpclient.getCredentialsProvider().setCredentials(new AuthScope("ch0016188", 8888), new UsernamePasswordCredentials("frederic_agneray", "pass"));

HttpPost httpPost = new HttpPost("http://ch0016188:8888/gateway/services/SID0003006");
httpPost.setHeader(new BasicHeader("Content-Type", "text/xml;charset=UTF-8"));
httpPost.setHeader(new BasicHeader("SOAPAction", "process"));
StringEntity s = new StringEntity(XML_DATA, "UTF-8");
httpPost.setEntity(s);

System.out.println("executing request" + httpPost.getRequestLine());
HttpResponse response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();

System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
System.out.println(EntityUtils.toString(response.getEntity()));
}
if (entity != null) {
entity.consumeContent();
}

// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
}

Wednesday, September 2, 2009

Using OWSM on multi-domain Active Directory

Lately we had to use Oracle Web Service Manager to Authenticate and Authorize web service user against our Active Directory.
That is pretty simple if your users are in a single domain, however our directory is separated in 4 domains: EAME, APAC, AMR and B2B domains.

So we tried to figure out a way to authenticate against all those domains.
1. The AD authentication step of OWSM does not allow multiple domain search
2. The LDAP authentication can be used to authenticate against a AD. And the LDAP query can search against multiple directory.

3. In the same way, AD authorization cannot be used against multiple domain
4. Then LDAP authorization cannot be used because AD directory use the attribute "member" instead of "uniqueMember" for LDAP directory.

So to fix this issue we had to build a custome step within OWSM. We decompile LDAPAccessControlStep and built ILayerLdapAccessControlStep. It is the same piece fo code but "uniqueMember" is replaced by "member".

ETL Process Through Email Attachment

Last June, one of my post was "A BPEL process that saves e-mail attachment".
The aim was to try to insert data within the ERP via an e-mail attachment.
For example, to load the "daily mineral figures" of South-Africa, the South-Africa manager was sending a mail to etl.load@mycompany.com with an attached file (an xml file). This attachment would be processed and its containing data inserted into the ERP.
Security was insured by a x.509 certificate signature.

This process is very convenient as sending a mail is an easy process and can be done with a limited access to the web.

We tried to enable this process with "Oracle BPEL Process Manager", but the following issues arise:
1. Nearly impossible to authenticate the certificate signature
2. Difficult to retrieve the attachment with the correct encoding
3. Difficult to retrieve more than one file
4. Impossible to move mail in other folder after processing
5. To deal with all the operations, lots of Java embedded code had to be written.
6. Mail with attachment bigger than 1MB could not be processed
This is not exhaustive, but the feature for BPEL PM that enable to start a process by receiving a mail, is not meant to deal with complex mail content.

So we decided to change our option and use the Java Mail API.
We used Quartz to schedule our process and the process was written in Java.
The operations are:
1. Call the IMAP server every 5 minutes to check mail box for incoming mail
2. Retrieve the attachments and copy them to the correct location
3. Send e-mail if an error occurred or if the attachment was correctly copied
4. Move the mail from "Inbox" to "Processed", "Error" or "Discard" folder

The process is hosted within our J2EE server and is a reliable and robust solution.

Post a message if you want the source code of this process.