When I decided to learn Java mapping, I searched SDN for blogs on Java mapping and found lot of blogs. Some of them were too technical and some of them given only coding and nothing else. As a developer, who did not have Java background, I found it very difficult to follow those blogs. So, I decided to come up with this blog post for beginners, which will give a basic understanding of how to write a Java mapping program.
What is parsing?
The literal meaning of parsing is “taking apart” or “breaking down” something into smaller segments. Technically when we say parsing of an XML document, we are breaking the XML file into individual elements and reading the data contained in the elements (body of the individual elements)
Why do we need parsing in Java mapping:
A typical Java mapping program takes the incoming XML message and transfers the data into target XML message structure. To do this the Java program first needs to read what is there in the incoming XML message. This is done by parsing or breaking down the XML document into individual elements.
Java provides two ways of parsing the XML document
- SAX ( Simple API for XML )
- DOM ( Document Object Model)
The subject of this blog is SAX so I am going to concentrate more on SAX parser.
Few things you should know about the SAX parser:
SAX parser is nothing but simple API for XML. In crude words set of classes used for reading the XML document
The five methods shown below are used when parsing the XML documents
startDocument
Called when the Parser starts parsing the Current XML File.
public void startDocument () throws SAXException {
...
...
}
endDocument
Called when the Parser Completes parsing the Current XML File.
public void endDocument () throws SAXException {
...
...
}
startElement
Called when the starting of the Element is reached. For Example if we have tag called <Title>...</Title>
, then this method is called when <Title>
tag is Encountered while parsing the Current XML File. The AttributeList Parameter has the list of all Attributes declared for the Current Element in the XML File.
public void startElement (String name, AttributeList attrs) throws SAXException {
...
...
}
endElement
Called when the Ending of the current Element is reached. For example in the above explanation, this method is called when </Title>
tag is reached
public void endElement (String name) throws SAXException {
...
...
}
characters
While Parsing the XML file, if extra characters like space or enter characters are encountered then this method is called. If you don’t want to do anything special with these characters, then you can normally leave this method blank. So this method can be used to read the values or body of the elements.
public void characters (char buf [], int offset, int len)
throws SAXException {
...
...
}
Lets take a simple example and understand how these methods work. The incoming message has below format
<?xml version="1.0"?>
<doc>
<para>Hello, world!</para>
</doc>
An event-based interface will break the structure of this document down into a series of linear events, such as these:
When the java program takes this message as input, as soon as system reads the first line (i.e., <?xml version="1.0"?>
the startDocument()
method is called then system reads next element <doc>
, now the startElement()
method is triggered, next the method is called again for <para>
element. Now as the element <para>
contains some body, characters method is called. After that system reads </para>
, which is end of the element <para>
. At this point system calls endElement()
method. Again system calls endElement()
, but this time for </doc>
element. Finally endDocument()
method is called when there are no elements left to read.
start document
start element: doc
start element: para
characters: Hello, world!
end element: para
end element: doc
end document
The SAX parser is also called event driven parser because it invokes the methods ( startDocument()
, startElement()
etc., ) as it reads the XML document.
What you should know and do before creating java mapping programs:
- First download the recent JDK ( java development kit) from web
- With in jdk folder you have bin folder, which contains all the java executable files.
- In environment variables add the path c:program filesjavajdk1.4bin
- For CLASSPATH add c:program filesjavajdk1.4lib
- Most importantly you need to know some core java concepts ( let me tell you this is not difficult. If I can do, you can as well do it)
(The path might be different when you install the JDK in your PC. The path I have mentioned is what I have used.)
After doing this download the aii.map.api.jar file and place it in bin folder. Add the path c:program filesjavajdk1.6binaii.map.api.jar to the CLASSPATH environment variable.
The jar file aii.map.api.jar resides in the XI server. Ask you basis guy to provide you this jar file. The path for the jar file in Xi server is j2eeclusterserver0appssap.comcom.sap.xi.services
The first thing we need for creating any mapping program is to create two message interfaces. So let’s start and create the data types , message types and message interfaces. I am not going to explain here in detail how to create them as it is very simple and straightforward. Any user working in XI or got trained should be in a position to do that.
The data type DT_OB_SAX_MAP contains two elements NUMBER1 and NUMBER2. The data type DI_IB_SAX_MAP has three elements ADD,MUL and SUB. The aim here is to take the two numbers and add , multiply and subtract them and pass the results to the respective elements in target message.
Message type MT_OB_SAX_MAP
Message type MT_IB_SAX_MAP
Message type MI_OB_SAX_MAP
Message interface MI_IB_SAX_MAP
Before creating the interface mapping, we need to create the Java mapping program.
We will first examine the source and target XML message structure.
<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_OB_SAX_MAP xmlns:ns0="http://learningxi.com">
<NUMBER1>1</NUMBER1>
<NUMBER2>1</NUMBER2>
</ns0:MT_OB_SAX_MAP>
The message has three elements MT_OB_SAX_MAP, NUMBER1 and NUMBER2.
<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_IB_SAX_MAP xmlns:ns0="http://learningxi.com">
<ADD>2</ADD>
<MUL>1</MUL>
<SUB>0</SUB>
</ns0:MT_IB_SAX_MAP>
As you see from the above XML structure, we have total four elements MT_IB_SAX_MAP, ADD, MUL and SUB.
- ADD element body is nothing but NUMBER1 + NUMBER2
- MUL element body is NUMBER1 * NUMBER2
- SUB element body is NUMBER1 – NUMBER2
Understand the java Mapping program:
package jmapsax;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.sap.aii.mapping.api.StreamTransformation;
import java.io.*;
import java.util.Map;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
/*IMPORT statement imports the specified classes and its methods into the program */
/*Every Java mapping program must implement the interface StreamTransformation and its methods execute() and setParameter() and extend the class DefaultHandler.*/
public class saxmapfinal1 extends DefaultHandler implements StreamTransformation{
/*Below is the declaration for all the variables we are going to use in the subsequent methods. */
private Map map;
private OutputStream out;
private boolean input1 = false;
private boolean input2 = false;
private int number1;
private int number2;
private int addvalue;
private int mulvalue;
private int subvalue;
String lineEnd = System.getProperty("line.separator");
/*setParamater() method is used to store the mapping object in the variable "map" */
public void setParameter (Map param) {
map = param;
}
public void execute (InputStream in, OutputStream out)
throws com.sap.aii.mapping.api.StreamTransformationException {
DefaultHandler handler = this;
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser saxParser = factory.newSAXParser();
this.out = out;
saxParser.parse(in, handler);
}
catch (Throwable t){
t.printStackTrace();
}
}
/*As seen above execute() method has two parameters "in" of type InputStream and "out" of type OutputStream. First we get a new instance of SAXParserFactory and from this one we create a new Instance of SAXParser. To the Parse Method of SaxParser, we pass two parameters, inputstream "in" and the class variable "handler".*/
/*Method "write" is a user defined method, which is used to write the string "s" to the outpurstream "out".*/
private void write (String s) throws SAXException{
try{
out.write(s.getBytes());
out.flush();
}
catch (IOException e){
throw new SAXException("I/O error", e);
}
}
public void startDocument () throws SAXException{
write("");
write(lineEnd);
write("");
write(lineEnd);
}
public void endDocument () throws SAXException {
write("");
try { out.flush();
}
catch (IOException e) {
throw new SAXException("I/O error", e);
}
}
public void startElement (String namespaceURI, String sName,
String qName, Attributes attrs) throws SAXException {
String eName = sName;
if ("".equals(eName)) eName = qName;
if(eName.equals("NUMBER1")) input1 = true;
if(eName.equals("NUMBER2")) input2 = true;
}
public void endElement (String namespaceURI, String sName, String qName) throws SAXException {
String eName = sName;
if ("".equals(eName)) eName = qName;
if(eName.equals("NUMBER1")) input1 = false;
if(eName.equals("NUMBER2")) input2 = false;
}
public void characters(char[] chars,int startIndex, int endIndex) throws SAXException {
String dataString =
new String(chars, startIndex, endIndex).trim();
if (input1) {
try {
number1 = Integer.parseInt(dataString);
} catch(NumberFormatException nfe){
}
}
if (input2) {
number2 = Integer.parseInt(dataString);
}
if (input2 == true){
addvalue = number1 + number2;
mulvalue = number1 * number2;
subvalue = number1 - number2;
write("" + addvalue +"");
write(lineEnd);
write("" + mulvalue +"");
write(lineEnd);
write("" + subvalue +"");
write(lineEnd);
}
}
}
When the parsing of XML message starts, first startDocument()
method is triggered as soon as program encounters the line <?xml version="1.0" encoding="UTF-8"?>
. so we will call write()
method by passing the <?xml version="1.0" encoding="UTF-8"?>
to argument “s”. The write()
method writes this string to the OutputStream. Similarly we will also pass the string <ns0:MT_IB_SAX_MAP xmlns:ns0="http://learningxi.com">
to write()
method. In between these statements write(LineEnd)
is used to introduce a newline.
Taking analogy from the example explained in the Sax parser section the sequence of method call is given below:
startDocument()
startElement() - <MT_OB_SAX_MAP>
startElement() - < NUMBER1>
characters() - body of NUMBER1 ( i.e 1 )
endElement() - </NUMBER1>
startElement() - <NUMBER2>
characters() - body of NUMBER2 ( i.e, 1)
At this point we calculate the values for ADD, MUL and SUB elements and call the write()
method to write these elements to the OutputStream out
.
endElement() -</NUMBER2>
endElement() - </MT_OB_SAX_MAP>
endDocument()
Now place the java file in a folder with name jmapsax ( this is package name we have specified in the java program). Compile the program and zip the java file and generated class file.
Create a new imported archive and import the zip file.
Imported archive ” newarchive”
Interface Mapping IM_SAX_MAP
click the test tab in the interface mapping and enter some integer values for NUMBER1 and NUMBER2. click on execute you will see the target message.
Interface testing tree view
Interface testing XML view
Sankar Rao Bhatta is an SAP NetWeaver Consultant with Intel, India. After completing M.Tech from IIT Bombay, he worked with IBM as SAP Consultant before joining Intel. Other areas of his expertise include SAP SRM and ABAP.