Wednesday, May 27, 2009

Import DVM using Java-Ant

While writing an Ant build script to deploy the BPEL/ESB processes, it became absolutely important to deploy/import the DVMs automatically using Ant build scripts. While surfing thru the web, I came across a piece of Java code that will accomplish this task. I have made few enhancements to the code which will dynamically get the DVM file details from a property file for import.

Pre-Requisites:

1. You will need to import the commons-codec-1.3.jar available in the SOA suite ($SOA_Home\Integration\esb\lib)
2. Download the commons-httpclient-3.1.jar from the internet (Any older version will throw errors!)
3. Import commons-logging.jar from $SOA_Home\Integration\esb\lib folder

Functional Aspects:

a.) The following piece of code will use a property file called ImportDVM.properties which will contain the dynamic parameters such as hostname, port number, username, password and more importantly the dvm file(s) location

b.) Multiple DVM files can be imported at a time by providing a comma (,) separated list of DVM file locations for the "dvm" parameter in the properties file

Java Source Code:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.Properties;
import java.util.StringTokenizer;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;

public class ImportDVM {
public static void main(String[] args) {
Properties props = new Properties();
try {
InputStream in = Class.forName("ImportDVM").getResourceAsStream("ImportDVM.properties"); // Properties file to define your dynamic parameters
props.load(in);
String esbHost = props.getProperty("hostname");
int esbPort = Integer.parseInt(props.getProperty("port"));
String username = props.getProperty("username");
String password = props.getProperty("password");
String fileLocation = props.getProperty("dvm"); //dvm file location
StringTokenizer st = new StringTokenizer(fileLocation, ",");
while (st.hasMoreTokens()) {
String dvm = st.nextToken();
importDVM(esbHost, esbPort, username, password, dvm);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void importDVM(String esbHost, int esbPort, String username, String password, String fileLocation) {
try {
InputStream is = null;
HttpClient client = new HttpClient();
int responseCode = 0;
client.getHttpConnectionManager().getParams().setConnectionTimeout(90000);

// Authenticate
String authUrl = "http://"+esbHost+":"+esbPort+"/esb/j_security_check?j_username="+username+"&j_password="+password;
GetMethod auth = new GetMethod(authUrl);
responseCode = client.executeMethod(auth);

// ImportDVM
File targetFile = new File(fileLocation);
PostMethod post = new PostMethod("http://"+esbHost+":"+esbPort+"/esb/esbConfiguration/executeCommand?action=ImportDVM");
post.setRequestHeader("User-Agent", "ESB Client/1.0");
//StringPart s1 = new StringPart("importType","map");
//StringPart s2 = new StringPart("importMode","overwrite");
//FilePart f1 = new FilePart(targetFile.getName(), targetFile);
Part[] parts = {new StringPart("importType","map"), new StringPart("importMode","overwrite"), new FilePart(targetFile.getName(), targetFile)};
System.out.println(Part.getLengthOfParts(parts));
post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
responseCode = client.executeMethod(post);
System.out.println("Response code: " + responseCode);
is = post.getResponseBodyAsStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
while ((c = is.read()) != -1) {
baos.write((char)c);
}
byte[] responseBody = baos.toByteArray();
post.releaseConnection();
String response = new String(responseBody);
System.out.println(response);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Executing from Ant:

So far so good. Now it turns out to be very simple. Just compile the class and call this using the "java" ANT task.
You got a class not found exception huh? Yup, you have forgotten to keep the Java class location in your classpath.

We are now good to go!

Monday, May 11, 2009

Issue with BPEL Date Functions

The Oracle BPEL date function xp20:current-dateTime() comes in very handy whenever we require to track/print the current system timestamp inside a BPEL process at runtime. However, there is a glitch with this function during the daylight savings timezone settings, as this function returns the timestamp 1 hr ahead of the actual time during the daylight savings. This issue was logged with Oracle and the issue was attributed to the JDK version (1.5.0_06) bundled with the SOA suite 10.1.3.3. To resolve this issue at hand, an upgrade to at least JDK version 1.5.0_16 is recommended.

However, to overcome this issue even more easily, you can use the Oracle BPEL XPath extension function ora:getCurrentDateTime() to get the current system timestamp exactly even during daylight saving settings. If you have the same issue, try this out and this should work as it worked fine for me ;)

Friday, May 8, 2009

Passing BPEL variables to XSL

I have always wondered, it would be great to pass runtime variable data from the BPEL process to a XSL file for processing within the transformation. To achieve this you can follow the steps as given below;

1. Create a custom schema (namely xslproperties.xsd) as given below & import this schema into your BPEL process.

<xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:p="http://schemas.oracle.com/service/bpel/common"
xmlns="http://schemas.oracle.com/service/bpel/common"
targetNamespace="http://schemas.oracle.com/service/bpel/common"
elementFormDefault="qualified">
<xsd:element name="parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="item" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="value" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

2. Create a variable (for instance, xslParameters) in your BPEL process of type xslproperties.xsd
3. Now, assign the values to this schema using a transformation activity. You can assign the variable name to the <name> element & variable value to the <value> element
4. If you have to pass multiple variables to the XSL, use the for-each element in the transformation. Optionally you can also build the schema using the "XML Fragment" assign operation and assign values to it
5. The processXSLT() function has 3 parameters. The first parameter holds the XSL file name, the second parameter is the input variable/data for the XSLT to process and the third parameter is the properties. We are now interested in the third parameter which helps us to pass the BPEL variables to the XSLT.
6. Pass the variable xslParameters (As created in step 2) as the third parameter as shown below;
ora:processXSLT('XSLT_File.xsl',bpws:getVariableData(’inputVariable’,'payload’),bpws:getVariableData('xslParameters '))
7. Now, you can obtain all the variable values inside the XSLT file using the <xsl:param name="variable1"/> instruction and you can use this just like a variable inside your XSL file