Skip to Content
Author's profile photo Ricardo Viana

Easy way to learn – Java Mapping using DOM – SAP PI 7.1+

Hi all,


     I will explain in this blog a easy way to do a javamapping using DOM for any mapping that you need, today I use javamapping for the most of mappings, because Graphic Mappings it´s limited in somecase hard to input a logic inside box, also I will explain the project case that I did.


Check this out and enjoy it.


What is a Parser?


     A parser breaks data into smaller elements, according to a set of rules that describe its structure. If the syntax of a data source has been described by grammar rules, a parser can use the grammar to parse the data source; that is, to break data elements such as address into smaller elements, such as house number,street number,city, pincode etc. The output of the parser is a parse tree. The parse tree expresses the hierarchical structure of the input data.

What is a DOM Parser?

     DOM(Document Object Model) is a platform- and language-neutral interface, that provides a standard model of how the objects in an XML object are put together, and a standard interface for accessing and manipulating these objects and their inter-relationships.

Why DOM parser?

  1. Converts XML into a tree of objects
  2. It’s possible to access any node within tree randomly
  3. Can insert/delete nodes within XML document
  4. Implements W3C standards for accessing XML

Whats the main difference between DOM and SAX ?

     DOM loads a whole XML file inside memory and SAX you can just check what node you want.

     I will not explain SAX in this blog.


Whats the difference between java mapping SAP PI version 7.0 and 7.1 ?

Into SAP PI 7.0 you must implement the method execute and SAP PI 7.1 you must implements the transform method.


public void execute(InputStream in, OutputStream out) throws StreamTransformationException {


public void transform(TransformationInput tInp, TransformationOutput tOut) throws StreamTransformationException {

Java Libs and SAP PI Versions:

SAP PI 7.1 lib for java mapping: aii_map_api.jar

SAP PI 7.0 lib for java mapping : com.sap.xpi.ib.mapping.lib.jar

Project Case:

     The project case was evolving 5 systems basically, one was a .NET Webservice, SAP PI (Middleware Layer), SAP BO NF-e 10.0 (Application Server – SAP Solution for Eletronic invoices to Brazil), SAP ECC 6.0 and and Governament Webservice System – SEFAZ.

Sem título.png

    Asyn to Sync brigde using ccBPM – I will not explain this steps into this document.


    I will not discuss about the integraction between SAP PI and ECC also layout of message, only about Webservice x SAP PI and layout interface.

     The requirement from .NET Webservice team was – ” I need send to you an interface with 3 process inside”

     The request mensagem:

    1. MM – Material moviments –  0..1
    2. FI – Financial bills – –  0..1
    3. NF-e – J1B1N Writer NF-e –  0..1

     I created a data type separate in BLOCK´s of process:

     Request Message:

      req.JPG

    The occurrences was defined 0..1, because sometime the web service could send only BlockMM or BlockFI or both, or only Block NF-e or three blocks.

     Response message:

     Now this is the point of parsing with DOM starts.

     So if the request message has only Block MM and Block FI  the Message Mapping could handly easy the mapping, but if the request has the BlockNF-e I needed use java mapping.

resp.JPG

     So I use DOM because, I must read all XML and check if the response message structure contains the Block NFe and tag <StringXMLNFe> with string of NF-e XML.

     From this tag <StringXMLNF-e>, I will extract the values from specifics tags andcreate the <RespuestaSefaz> structure into target response message.

Java code

  Check the attachment file, but below I will explore the main part and important part of the java code:


public void transform(TransformationInput tInp, TransformationOutput tOut)throws StreamTransformationException {
/*-----------------------------------------------------------
* Create a tracelog variable
*-----------------------------------------------------------*/
AbstractTrace absTraceLog = this.getTrace();
absTraceLog.addDebugMessage("\n Start Java Mapping-");
/*-------------------------------------------------------------------------
* Create a variabloe inpxml to recebive the stream converted into String
*-------------------------------------------------------------------------*/
String inptxml = convertStreamToString(tInp.getInputPayload().getInputStream());
try {
/*-------------------------------------------------------------------------
* Creating a dom document "doc"
*-------------------------------------------------------------------------*/
DocumentBuilder domFactory = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Transformer tf = TransformerFactory.newInstance().newTransformer();
Document doc = domFactory.parse(tInp.getInputPayload().getInputStream());
doc.getDocumentElement().normalize();
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
if (inptxml.contains("XMLNFe")) {
/*-------------------------------------------------------------------
* Creating a Nodelist x to receive a whole xml tag files
*------------------------------------------------------------------*/
NodeList x = doc.getDocumentElement().getElementsByTagName("*");
/*-----------------*
* Loop  *
*-----------------*/
for (int i = 0; i < x.getLength(); i++) {
Node xml1 = x.item(i);
if (xml1.toString() != ("#text") && xml1 != null&& xml1.getNodeType() == Node.ELEMENT_NODE) {
absTraceLog.addDebugMessage(" Os respectivos elementos são <"+ xml1.getNodeName()+ "> e está no index: " + i);








With this part above, until lineDOMSource source = new DOMSource(doc); you can use for do any java mapping into SAP PI 7.1+

The main part of the java code to read the whole xml document in one shot.


NodeList x = doc.getDocumentElement().getElementsByTagName("*");





So if this code above you dont need to do a loop inside loop to read nodes.

Basically * means into XSLT language, read a whole xml file.

Checking node <XMLNFe> element without “<open and close tags>”



if(((Element)xml1).getParentNode().getNodeName().equals("ns1:NotaFiscalResponse") &&
                          ((Element)xml1).getTagName().equals("ns1:XMLNFe")){
                            tagXmlNFe = xml1;
                            rootNFResponse = tagXmlNFe.getParentNode();









If found the tag XMLNFe it´s means that I need create the structure <RespustasSefaz>, if not the menssage contains only BlockMM and BlockFI so it´s a pass thought into java code.

Extracting values from xml string inside tag <StringXMLNFe>


chNFe = inptxml.substring(inptxml.indexOf("<chNFe>") + 7,inptxml.indexOf("</chNFe>"));
tpAmb = inptxml.substring(inptxml.indexOf("<tpAmb>") + 7,inptxml.indexOf("</tpAmb>"));
dhRecbto = inptxml.substring(inptxml.indexOf("<dhRecbto>") + 10,inptxml.indexOf("</dhRecbto>"));
nProt = inptxml.substring(inptxml.indexOf("<nProt>") + 7,inptxml.indexOf("</nProt>"));
cStat = inptxml.substring(inptxml.indexOf("<cStat>") + 7,inptxml.indexOf("</cStat>"));
xMotivo = inptxml.substring(inptxml.indexOf("<xMotivo>") + 9,inptxml.indexOf("</xMotivo>"));
digestVal = inptxml.substring(inptxml.indexOf("<digVal>") + 8,inptxml.indexOf("</digVal>"));
serie = inptxml.substring(inptxml.indexOf("<serie>") + 7,inptxml.indexOf("</serie>"));
nNF = inptxml.substring(inptxml.indexOf("<nNF>") + 5,inptxml.indexOf("</nNF>"));
cDV = inptxml.substring(inptxml.indexOf("<cDV>") + 5,inptxml.indexOf("</cDV>"));
cNF = inptxml.substring(inptxml.indexOf("<cNF>")+ 5,inptxml.indexOf("</cNF>"));










Creating the structure <RespustaSefaz> and internal children values into target response message:

/*—————————————————————-

* <ns1:RespuestaSefaz>

*—————————————————————-

*<ns1:RespuestaSefaz>

*      <ns1:AutorizadaPorSefaz> = #100 = true/false

*      <ns1:ClaveAcceso> =  <chNFe>

*      <ns1:Codigo> = <cNF>

*      <ns1:CodigoAmbiente> = <tpAmb>

*      <ns1:CodigoEstado> = <cStat>

*      <ns1:DigestValue> = <digVal>

*      <ns1:DigitoVerificador> = <cDV>

*      <ns1:FechaRecibido> = <dhRecbto>

*      <ns1:Motivo> =  <xMotivo>

*      <ns1:NroNotaFiscal> = <nNF>

*      <ns1:NroSerieNotaFiscal> = <serie>

*      <ns1:NumeroProtocolo> = <nProt>

*</ns1:RespuestaSefaz>

*——————————————————————*/

Creating the structures nodes:


respostaSefaz = doc.createElement("ns1:RespuestaSefaz");
autorizadaPorSefaz = doc.createElement("ns1:AutorizadaPorSefaz");
claveAcceso = doc.createElement("ns1:ClaveAcceso");
codigo = doc.createElement("ns1:Codigo");
codigoAmbiente = doc.createElement("ns1:CodigoAmbiente");
codigoEstado = doc.createElement("ns1:CodigoEstado");
digestValue = doc.createElement("ns1:DigestValue");
digitoVerificador=doc.createElement("ns1:DigitoVerificador");
fechaRecibido = doc.createElement("ns1:FechaRecibido");
motivo = doc.createElement("ns1:Motivo");
nroNotaFiscal = doc.createElement("ns1:NroNotaFiscal");
nroSerieNotaFiscal = doc.createElement("ns1:NroSerieNotaFiscal");
nroProtocolo = doc.createElement("ns1:NumeroProtocolo");









Inserting values into the new nodes created above:



/*------------------------------------------------------------------------------
* Inserting the values into new tags from values extracts
*------------------------------------------------------------------------------*/
autorizadaPorSefaz.appendChild(doc.createTextNode(cStat.replace(cStat, "true")));
claveAcceso.appendChild(doc.createTextNode(chNFe));
codigo.appendChild(doc.createTextNode(cNF));
codigoAmbiente.appendChild(doc.createTextNode(tpAmb));
codigoEstado.appendChild(doc.createTextNode(cStat));
digestValue.appendChild(doc.createTextNode(digestVal));
fechaRecibido.appendChild(doc.createTextNode(dhRecbto));
motivo.appendChild(doc.createTextNode(xMotivo));
nroNotaFiscal.appendChild(doc.createTextNode(nNF));
nroSerieNotaFiscal.appendChild(doc.createTextNode(serie));
nroProtocolo.appendChild(doc.createTextNode(nProt));









Creating the structures with values inside respective nodes:


/*---------------------------------------------------------------------
* Criando a estrutura <ns1:RespuestaSefaz> e inserindo as tags filhas
*---------------------------------------------------------------------*/
respostaSefaz.appendChild(autorizadaPorSefaz);
respostaSefaz.appendChild(nroNotaFiscal);
respostaSefaz.appendChild(nroSerieNotaFiscal);
respostaSefaz.appendChild(claveAcceso);
respostaSefaz.appendChild(codigoAmbiente);
respostaSefaz.appendChild(codigoEstado);
respostaSefaz.appendChild(digestValue);
respostaSefaz.appendChild(fechaRecibido);
respostaSefaz.appendChild(motivo);
respostaSefaz.appendChild(nroNotaFiscal);
respostaSefaz.appendChild(nroSerieNotaFiscal);








As you can see at target msg response, the node <RespustaSefaz> it was at specific possition, so I needed to find the position and insert structure and elements:


rootNFResponse.insertBefore(respostaSefaz, tagXmlNFe);
absTraceLog.addDebugMessage(" O elemento <"+respostaSefaz.getNodeName()+"> foi inserido acima da tag <"+ tagXmlNFe.getNodeName() + ">"
+ "que fica na estrutura <"+ rootNFResponse.getNodeName() + ">");
source = new DOMSource(doc);
result = new StreamResult(tOut.getOutputPayload().getOutputStream());
tf.transform(source, result);
}








After developed a java code into NWDS, you just need save it as .jar file and upload into SAP PI, as image below:

Capture.JPG

Check the test into Operation Mapping

Capture2.JPG

I hope that with this document helps you to understand the concept, when and how to develop java mapping without misterious.

Just one thing the code attached all coments is portuguese language !!

Kind regards,

BR.

Ricardo Viana.

Assigned tags

      28 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Nice work buddy..

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Thanks Idrajit.

      Author's profile photo Ajeya Vaani
      Ajeya Vaani

      Thanks dude. I'm a beginner and I was in need of a blog like this. Thank you very much.

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Ajeya thanks for comment, I´m glad to help.

      You welcome.

      Author's profile photo Former Member
      Former Member

      Hi Ricardo,

      Thanks for sharing this blog.Really appreciate your effort.

      Regards,

      Abhi

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Hi Abhimav,

      Thanks for comment buddy.

      I´m glad for help.

      Regards,

      Author's profile photo Former Member
      Former Member

      Ahh, GREAT Ricardo!!!

      Congratulations!!! 😀

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Luuu,

      Thanks 😀

      Author's profile photo Stefan Hilpp
      Stefan Hilpp

      Thanks for sharing...appreciate the effort

      Stefan

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Im Glad for share Stefan !! Thanks

      I hope now every body will do java mapping easy, with DOM 😀

      Author's profile photo Former Member
      Former Member

      Cool. Nice to see you here Viana!

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Hey Chagas,

      It´s a pleasure receive msg from you here, in PI WORLD ! rsrs.. my friend.

      Time to share knowledge around world, not only in Brazil.

      I´m not selfish rsrs.

      See you.

      Author's profile photo Hareesh Gampa
      Hareesh Gampa

      Simple n clear.. Thanks Ricardo

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Thanks Hareesh !!

      Author's profile photo Harish Mistri
      Harish Mistri

      Thanks Ricardo for sharing the detail.

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Welcome Harish !! ;D

      I´m doing another interface - FILE TO RFC TO MAIL.

      I will explain into this next blog about XiMail30.xsd 😀

      See ya

      Author's profile photo Former Member
      Former Member

      Hi Recardo,

      Please  update the content with

      In SAP PI 7.0 you must implement the method execute and  from SAP PI 7.1 you must implement the transform method.

      Java Libs:

      SAP PI 7.0 lib for java mapping: aii_map_api.jar

      SAP PI 7.1 lib for java mapping : com.sap.xpi.ib.mapping.lib.jar

      Best Regards

      Raja

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      THanks Raj,

      I did update.

      About libs it was correct.

      Regards,

      Ricardo Viana,

      Author's profile photo Former Member
      Former Member

      Thanks for updating.

      Please check the wiki : Where to get the libraries for XI development - Process Integration - SCN Wiki which gave the information about libraries.

      Regards

      Raj

      Author's profile photo Monikandan Panneerselvam
      Monikandan Panneerselvam

      Great Job Ricordo

      Author's profile photo Sunil Mavachee
      Sunil Mavachee

      Any lay man can understand.. greatly simplified.! Keep writing.!

      Regards,

      Sunil

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Thanks Sunil !!

      Author's profile photo Former Member
      Former Member

      Great blog. Helps med to get a quick overview of the messy parts of the java mapping like parsers and PI versions.

      Thanks,

      Maria Lande

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Thanks Lande !!

      I will write something nice soon.

      Author's profile photo Angelo Antonello Borges
      Angelo Antonello Borges

      Great article, but the use of DOM is not recommended. The PI makes use of Message Queues and Pipelines to split the processing of every context node. When you use the DOM you're killing this principle/resource.

      Your solution applies well in a few requests per second, and only in that case.

      Best regards,

      Angelo

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Angelo,

      Thanks for you comment, I agree with you but in my case I didn´t find way to do it via MM or XLST.

      The requirement was once a or two a day for this interfacace, work really properlly.

      Regards,

      BR.

      Ricardo Viana.

      Author's profile photo Annapureddy Kasi viswanath
      Annapureddy Kasi viswanath

      Nice stuff.

      Could you please explain the below loop.

      1. for (int i = 0; i < x.getLength(); i++) { 
      2. Node xml1 = x.item(i); 
      3. if (xml1.toString() != ("#text") && xml1 != null&& xml1.getNodeType() == Node.ELEMENT_NODE) { 
      4. absTraceLog.addDebugMessage(" Os respectivos elementos são <"+ xml1.getNodeName()+ "> e está no index: " + i); 

      If you have any kind of java mapping stuff(explaination of Java API used in SAP PI) pls forward to annapureddy.1150@gmail.com

      Author's profile photo Ricardo Viana
      Ricardo Viana
      Blog Post Author

      Hi Annapureddy.

      1. for (int i = 0; i < x.getLength(); i++) {  --> Collecting the size of xml
      2. Node xml1 = x.item(i);  --> Looking for expecific node into xml file.
      3. if (xml1.toString() != ("#text") && xml1 != null&& xml1.getNodeType() == Node.ELEMENT_NODE) {  - This condition I'm excluding the values "< >" from xml tags and pick up only the node value.
      4. absTraceLog.addDebugMessage(" Os respectivos elementos são <"+ xml1.getNodeName()+"> e está no index: " + i);  --> This is print the values of nodes to check if I get correct one.


      Basically this is it.


      The java code it's attached just need extract that and adapt if for your xml.


      Regards,


      BR.


      Viana.