Skip to Content

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.

To report this post you need to login first.

28 Comments

You must be Logged on to comment or reply to a post.

    1. Ricardo Viana 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.

      (0) 
    1. Ricardo Viana 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

      (0) 
  1. Raja S Malledi

    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

    (0) 
  2. Lande Maria

    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

    (0) 
  3. 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

    (0) 
    1. Ricardo Viana 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.

      (0) 
  4. 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

    (0) 
    1. Ricardo Viana 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.

      (0) 

Leave a Reply