Update 19 May 2014:JAR file also available for download at GitHub repository
Background
Whenever we need to develop Java mappings in PI, often it involves a lot of copy-paste of codes and doing the same tasks again and again. Most of this effort is to comply with the Java Mapping API provided in PI. In this article, I will introduce an approach that can simplify developments of Java Mapping in PI. A similar approach was previously introduced in the following article XI Java Mapping Helper (DOM) by Alessandro Guarneri. In this article, the design is based on the new API utilizing AbstractTransformation class from PI7.1 onwards. Hopefully this might also lower the entry barrier for those who are contemplating developing Java mappings but are new to it.
Concept & Design
The idea is to "package" commonly reused codes together, which then enables the developer to focus on the specific logic for a particular requirement. This approach is based on the Strategy Pattern using Abstract Classes.
In general, following are the sequence of steps required for a Java Mapping.
- Parsing of Input
- Generating the output content
- Convert output content to output stream
As mentioned above, steps 1 and 3 are always the same most of the time. The difference between mappings are often for step 2 to generate the output content. As such we can encapsulate the logic in steps 1 and 3 into an abstract base class.
Also, there is possibility of different type of input/output content (plain, XML, binary, etc), and each of these require specific logic for parsing and stream generation. Therefore there will be a second tier of abstract classes which controls the correct sequence of logic for each conversion type.
The following table lists the classes in this design.
Class | Description |
---|---|
AbstractMappingBase | Base super class |
AbstractDOM2DOM | Extends AbstractMappingBase - Controls logic for DOM to DOM processing |
AbstractDOM2Plain | Extends AbstractMappingBase - Controls logic for DOM to Plain processing |
AbstractPlain2Plain | Extends AbstractMappingBase - Controls logic for Plain to Plain processing |
AbstractPlain2DOM | Extends AbstractMappingBase - Controls logic for Plain to DOM processing |
Below is an example of the logic in AbstractPlain2DOM class. Firstly, the input data is parsed and stored in the array of String (representing each line of input payload). Then the output contents are generated in DOM format. Lastly, the DOM output is transformed to the output stream.
ArrayList<String> inputContents = parsePlainInput(input.getInputPayload().getInputStream()); Document outputDoc = getDocumentBuilder().newDocument(); generateOutput(inputContents, outputDoc); transformDocumentToStream(outputDoc, output.getOutputPayload().getOutputStream(), indentOutputXML);
Each of the subclasses has an abstract generateOutput method. It is this method that needs to be implemented in a custom mapping class that extends the corresponding abstract class. Below is a table listing the input/output parameters of the abstract method for each of the classes.
Class | Modifier & Type | Method & Description |
---|---|---|
AbstractDOM2DOM | abstract void | generateOutput (Document inDoc, Document outDoc) Construct DOM output based on DOM input |
AbstractDOM2Plain | abstract StringBuilder | generateOutput (Document inDoc) Generate String output based on DOM input |
AbstractPlain2Plain | abstract StringBuilder | generateOutput (ArrayList<String> inContents) Generate String output based on input of String array |
AbstractPlain2DOM | abstract void | generateOutput (ArrayList<String> inContents, Document outDoc) Generate DOM output based on input of String array |
Example of Mapping Implementation
Now we go to the actual work to be done. In this example, I will develop the Java Mapping directly in ESR based on the technique shared by Sunil Chandra. Alternatively, this can be done in the normal way in Eclipse/NWDS - just need to remember to include the JAR file below in the build path.
Step 1
Import the JAR file into ESR as an Imported Archive (this can be skipped for further developments.)
Step 2
Create Message Mapping with dummy source and target.
Step 3
In the Functions tab, include the archive, and add the import for com.equalize.xpi.esr.mapping. If you are using DOM related functions, import org.w3c.dom as well.
Step 4
Write code in "Attributes and Methods" section.
Essentially, there are only 2 things to do here. First of all, implement transform method of AbstractTransformation. The following code can be copied as-is.
@Override public void transform(TransformationInput input, TransformationOutput output) throws StreamTransformationException { AbstractMappingBase map = new CustomMap(); map.process(input, output, this.getTrace()); }
Secondly, and more importantly is to code the logic for the output content. To do this, create a local CustomMap class that extends from one of the above abstract classes (AbstractPlain2Plain in this example). Then implement the generateOutput method. The following code just adds a prefix for each of the input lines - HD for first line, FT for last line and IT for everything in between.
// Local class with logic for output generation class CustomMap extends AbstractPlain2Plain { @Override protected StringBuilder generateOutput(ArrayList<String> inContents) { StringBuilder sb = new StringBuilder(); int count = 0; for (String line : inContents) { if (count == 0) { sb.append("HD"); } else if (count == inContents.size()-1) { sb.append("FT"); } else { sb.append("IT"); } sb.append(line); sb.append("\n"); count++; } setPlainOutputEncoding("UTF-8"); return new StringBuilder(sb.toString()); } }
Step 5
Test the mapping.
Conclusion
As you can see, the development of the Java mapping for any requirement has been significantly simplified. The developer no longer needs to handle the parsing and the stream conversion, and therefore can fully focus on the specific content generation.
Also, currently there are only 4 different mapping subclasses, handling DOM and plain text processing. This can be easily extensible in the future to include other types, i.e. SAX.
Source code and JAR
The Java source codes are available in the following GitHub repository. Also included are sample implementation source codes for each of the abstract class above.
PI_JavaMappingLib at engswee's GitHub
The JAR file (with source codes) are attached below. However, due to SCN file import limitations, it has been renamed as .TXT. To obtain the JAR file, please follow the steps below:
- Download the ZIP file.
- Extract contents of ZIP file.
- Remove .TXT extension of file (so that the extension becomes .JAR)
Update: JAR file is also available for direct download at GitHub
Reference
The following article Easy way to learn - Java Mapping using DOM - SAP PI 7.1+ by Ricardo Viana is a useful resource to learn DOM based processing.