Quantcast
Channel: SCN : All Content - Process Integration (PI) & SOA Middleware
Viewing all articles
Browse latest Browse all 7030

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

$
0
0

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 class execute and SAP PI 7.1 you must implements the transform class.


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.

 

aew.png

 

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

 

     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 line " DOMSource 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.


Viewing all articles
Browse latest Browse all 7030

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>