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.
Hi Sankar,
Great Job Indeed..Keep it UP ! ! !
What if everyone in the world explains the things/concepts as clear as this article explains about Java Mapping, without any doubt everyone would have been educated very easily without any pain.
Thank you very much for an excellent article. Waiting for more…Please keep posting…
Thanks
Krishna
Hi Sanker,
Great work. I also confused like you before. Now I got full idea.Keep it up.
Please keep posting your article.
Thank
Madhu
Hey Sankar,
/*Every Java mapping program must implement the interface StreamTransformation and its methods execute() and setParameter() and extend the class DefaultHandler.*/
Do you think it is mandatory to extend the class DefaultHandler in all Java Mappings?
Can I not by-pass it?
Thanks,
Senthil
hello sir,
Thanks a lot for this article.you have done wonderfully well to make it for beginners.no hi-fi concepts and superb.keep posting sir
Your Blogs are great !
Keep blogging!
Hi –
I just wanted to say ‘thank you'” for your wonderful and clear explanation of Java mappings. Great Job!
Best Regards,
Eli
Great one. clearly explained. well done.
Thx
Saran
Hi sankar,
Thanks a lot for your clear explanation on java mapping..
It helped me a lot .keep it up.Hope u post more articles …..
Thanks,
Hemanth.
Hi Sankar Bhatta,
Thanks.
You are great. Keep posting more stuff.
God Bless.
Peter
I think you just made my day. Thanks for a great job.
hi
Thanks for good explanation but i didnt understand
how the start and end elements
for MT_IB_SAX_MAP ,ADD,MUL, SUB
are written in the output ??
Can you please clarify?
thanks
Uday
Riyaz,
with the Code you Provided where exactly it tells the system to create Output elements. Is this code missing ?
SAX parsing is event-based, so you wont find individual node names. The code is complete. Please try it out yourself so as to understand it better.
The parse method parses the input xml document. Different methods like startDocument(), startElement() are invoked at appropriate events. The code within these methods is used to genrate the output document.
Hi Shankar,
I have seen so many blogs for Java mapping,but this Blog is the best blog .
Thanks
Gopi
Hi sanker/riyaz,
u guys are doing gr8 contribution. really appreciable.
I am verymuch new to java.
I was able to understand the whole stuff though , even as a beginner.
But, i have simple question.
How do we get into java editor for creating mapping program & testing it.
After installing jdk, how do we get into java editor.
Thanks again guys.
santosh.
You will need to install a Java development environment e.g. Eclipse or NWDS (NetWeaver Developer Studio).
hallo riyaz,
i get the error
Linkage Error when loading class Mapping; details: java.lang.UnsupportedClassVersionError
when i test my mapping program.
can you help me please?
Yousef
Make sure your mapping class file and all Java libraries used by the mapping program are present in repository. You can import all required libraries as separate imported archives in IR/ESR.
hi Riyaz,
i have solved the problem, but now i get the error
Unable to display tree view; Error when parsing an XML document (Content is not allowed in prolog.)
i use PI 7.1^and jdk 1.5
i dont know what is the problem.
Please test your mapping program locally before importing into IR/ESR. This should help you resolve the issues. Most likely you are missing out on closing some XML tags.
hallo riyaz,
I see value in the SAX parser, so i tried it out twice. I am able to setup the JDK toolkit, JCreator LE, compile a class and import the class for use in the interface mapping test with no problems. When i run an interface mapping test using the following :
100
200
I get the results XML NOT WELL FORMED on the receiver side, the sender XML is fine as XI produced the XML and i send it thru some WELLFORMEDNESS software i down loaded. I debugged the program that is identical to the one you supply in your example with your exact mapping and it is failing in the very start at STARTDOCUMENT throwing an exception(prints two blank lines) and then failing to produce any XML , XI displays XML NOT WELL FORMED .
the results side shows only the following but not the XML as the process failed to build the XML producing :
I thought maybe my program was bad so i tried it a second time with your XI messages and program you supplied , same results . I wonder about how it interpets the second line(ROOT) is causing problems
Any ideas, do i need to do some preliminary setup or any kind ? XI does most the work, please advice.
Thanks
riyaz,
ignore previous message , i found my error. thanks
Hi Sanker/Riyaz,
Great Post !!! Thanks.
Can you please explain in similar way how to parse and work with DOM.
Regards,
Pallab
Hi Riyaz,
where did you “in code” setup elements () of message and its values ?
Thanks for the answer.
Ifo