cancel
Showing results for 
Search instead for 
Did you mean: 

java mapping help pls

Former Member
0 Kudos

hi all,

I've a source structure like this below in PI.

<MAT>

<doc type>pdf</doc type

<subnumber>1234</subnumber>

<id>45ABC<id>

<matno>ABCD</matno>

<filename>transaction1.pdf</filename>

</MAT>

target structure would be the same but one more field <filecontent> which is bytearray content such as content=[101, 115, 116, 13, 10, 84, 101, 115, 116, 13, 10, 84, 101, 115, 116, 13, 10, 84, 101, 115, 116, 13, 10, 13, 10, 84, 101, 115, 116, 13, 10, 84, 101, 115, 116, 13, 10, 13, 10, 84, 101, 115, 116, 13, 10, 13, 10, 84, 101, 115, 116, 13, 10, 84, 101, 115, 116, 13, 10]

<MAT>

<doc type>pdf</doc type

<subnumber>1234</subnumber>

<id>45ABC<id>

<matno>ABCD</matno>

<filename>transaction1.pdf</filename>

<filecontent>bytearraycontent</filecontent

</MAT>

And target is HTTP post for posting the above attribute names and values in the body of HTML

I am writing a java mapping program because I have to read the <filename> tag value from the incoming xml and read the file from PI server location and convert the file content to bytearray and also to map it to target structure for HTTP post. I am requesting help from java experts here in modifying the program according to this requirement. pls help

package com.usahealth.mapping;

import java.io.InputStream;

import java.net.URL;

import java.net.URLConnection;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import com.sap.aii.mapping.api.AbstractTrace;

import com.sap.aii.mapping.api.AbstractTransformation;

import com.sap.aii.mapping.api.StreamTransformationException;

import com.sap.aii.mapping.api.TransformationInput;

import com.sap.aii.mapping.api.TransformationOutput;

public class ReadAttrMap extends AbstractTransformation {

  @Override

  public void transform(TransformationInput in, TransformationOutput out)

  throws StreamTransformationException {

  AbstractTrace trace = null;

  try {

  // Initialize Trace

  trace = getTrace();

  // Get Input Message as DOM

  DocumentBuilderFactory docBFactory = DocumentBuilderFactory

  .newInstance();

  docBFactory.setNamespaceAware(true);

  DocumentBuilder docBuilder = docBFactory.newDocumentBuilder();

  Document inDoc = docBuilder.parse(in.getInputPayload()

  .getInputStream());

  inDoc.getDocumentElement().normalize();

  // Read from PayLoad  - here is where I need help to read the filename - convert it to byte array and read other xml tag values and pass  to target structure for HTTP post. I am using HTTP receiver adapter for posting

 

  } catch (Exception e) {

  trace.addInfo(e.getMessage());

  throw new StreamTransformationException("Mapping Exception: "

  + e.getMessage(), e);

  }

  }

}

thx

mike

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Hi Michael

I have modified the java mapping so that it will return the output in the format mentioned in the blog.

&doc_type=pdf&subnumber=1234&id=45ABC&matno=ABCD&filename=transaction1.pdf&filecontent=[116,104,105,115,32,105,115,32,116,101,115,116,32,102,105,108,101]

Use this code and see if the HTTP post works successfully or not


package com.sap;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import com.sap.aii.mapping.api.AbstractTransformation;

import com.sap.aii.mapping.api.StreamTransformationException;

import com.sap.aii.mapping.api.TransformationInput;

import com.sap.aii.mapping.api.TransformationOutput;

public class populateTarget extends AbstractTransformation {

  public void transform(TransformationInput arg0, TransformationOutput arg1)

  throws StreamTransformationException {

  // TODO Auto-generated method stub

  this.execute(arg0.getInputPayload().getInputStream(), arg1

  .getOutputPayload().getOutputStream());

  }// end of transform

  public void execute(InputStream in, OutputStream out)

  throws StreamTransformationException {

  try {

  DocumentBuilderFactory tfactory = DocumentBuilderFactory

  .newInstance();

  DocumentBuilder tbuilder = tfactory.newDocumentBuilder();

  Document doc = tbuilder.parse(in);

  Document newdoc = tbuilder.newDocument();

  String outputxml = "";

  NodeList nlList = doc.getElementsByTagName("MAT"); // reading the root from input file

  Element root = (Element) nlList.item(0);

  // building the HTTP body

  String doctype = root.getChildNodes().item(1).getNodeName();

  String docval = root.getChildNodes().item(1).getTextContent();

  outputxml = outputxml + "&" + doctype + "=" + docval;

  String subnum = root.getChildNodes().item(3).getNodeName();

  String subval = root.getChildNodes().item(3).getTextContent();

  outputxml = outputxml + "&" + subnum + "=" + subval;

  String id = root.getChildNodes().item(5).getNodeName();

  String idval = root.getChildNodes().item(5).getTextContent();

  outputxml = outputxml + "&" + id + "=" + idval;

  String matnum = root.getChildNodes().item(7).getNodeName();

  String matval = root.getChildNodes().item(7).getTextContent();

  outputxml = outputxml + "&" + matnum + "=" + matval;

  String fname = root.getChildNodes().item(9).getNodeName();

  String filename = root.getChildNodes().item(9).getTextContent();

  outputxml = outputxml + "&" + fname + "=" + filename;

  // read the file from PI AL11 server and generate the byte content array

  

  byte[] fileArray = null;

  try {

  fileArray = getBytesFromFile(new File("/usr/sap"+filename)); // use the acutal Al11 path here

  } catch (IOException e) {

  e.printStackTrace();

  }

  String data = "";

  if (fileArray != null) {

  for (int i = 0; i < fileArray.length; i++) {

  data = data + fileArray[i];

  if (i < fileArray.length - 1) {

  data = data + ",";

  }

  }

  }

  outputxml = outputxml + "&filecontent" + "=" + "[" + data + "]";

  out.write(outputxml.getBytes("UTF-8"));

  } catch (Exception e) {

  e.printStackTrace();

  }

  } // end of execute

  // function to get bytes from a input file

  private static byte[] getBytesFromFile(File file) throws IOException {

  InputStream is = new FileInputStream(file);

  // Get the size of the file

  long length = file.length();

  /*

  * You cannot create an array using a long type. It needs to be an int

  * type. Before converting to an int type, check to ensure that file is

  * not loarger than Integer.MAX_VALUE;

  */

  if (length > Integer.MAX_VALUE) {

  System.out.println("File is too large to process");

  return null;

  }

  // Create the byte array to hold the data

  byte[] bytes = new byte[(int) length];

  // Read in the bytes

  int offset = 0;

  int numRead = 0;

  while ((offset < bytes.length)

  && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {

  offset += numRead;

  }

  // Ensure all the bytes have been read in

  if (offset < bytes.length) {

  throw new IOException("Could not completely read file "

  + file.getName());

  }

  is.close();

  return bytes;

  } // end of getBytesFromFile

}

Former Member
0 Kudos

God Bless u indrajit !! thx ..will let you know. Marking as helpful and will change it to correct answer soon

mike

Former Member
0 Kudos

hi Indrajit

There is a slight change in the input structure. They can send as many file names as required in one input request. We have to read each file name and create the target structure.

<MAT>

<doc type>pdf</doc type

<subnumber>1234</subnumber>

<id>45ABC<id>

<matno>ABCD</matno>

<file>  0..unbounded

<file_name>file1.pdf<file_name>     ----->name of the first file

<file_id>2y7hsjsj</file_id>             -------------->unique id of the first file

<file_type>pdf</file_type>             --------------->type of the file

<file_name>file2.xml<file_name>   ------------->name of the second file

<file_id>8mnk9<file_id>               -----------------unique id of the second file

<file_type>xml<file_type>             ------------------>type of the file

<file_name>file3.xml>                     ----------------->name of the third file

<file_id>e783kj3k3</file_id          ---------------->unique id of the third  file

<file_type>xml</file_type>        -------------->type of the file

-------------------------                 

------------------------

------------------------

---------------------

</file

</MAT>

So the <file> is 0..unbounded structure.

I have to create a target structure like this below.

<MAT>

<doc type>pdf</doc type

<subnumber>1234</subnumber>

<id>45ABC<id>

<matno>ABCD</matno>

<file>  0..unbounded

<file_content>file1.pdf<file_name>     ----->byte array content of the first file

<file_id>2y7hsjsj</file_id>             -------------->unique id of the first file

<file_type>pdf</file_type>         --------------->type of the file

<file_content>file2.xml<file_name>   ------------->byte array content of the second file

<file_id>8mnk9<file_id>               -----------------unique id of the second file

<file_type>xml</file_type>             ---------------------->type of the file

<file_content>file3.xml>                     ----------------->byte array content of the third file

<file_id>e783kj3k3</file_id          ---------------->unique id of the third  file

<file_type>xml<file_type>  --------------->type of the file

-------------------------                 

------------------------

------------------------

---------------------

</file

</MAT>

I am writing a java mapping program to read each <filename> tag value from the incoming xml and read the file from PI server location and convert the file content to bytearray and also to map it to target structure which would be XML. There is no more &and = in the target structure. It is plain XML. Can you please help in revisiting the java mapping program based on this change of requirement. I really appreciate your help


thx

mike





Former Member
0 Kudos

There is a mistake in the requirement above. Correcting the input structure and output structure

Input structure

<MAT>

<doc type>pdf</doc type

<subnumber>1234</subnumber>

<id>45ABC<id>

<matno>ABCD</matno>

<file>  0..unbounded

<file_name>file1.pdf<file_name>     ----->name of the first file

<file_id>2y7hsjsj</file_id>             -------------->unique id of the first file

<file_type>pdf</file_type>             --------------->type of the file

</file>

<file>

<file_name>file2.xml<file_name>   ------------->name of the second file

<file_id>8mnk9<file_id>               -----------------unique id of the second file

<file_type>xml<file_type>             ------------------>type of the file

</file>

<file>

<file_name>file3.xml>                     ----------------->name of the third file

<file_id>e783kj3k3</file_id          ---------------->unique id of the third  file

<file_type>xml</file_type>        -------------->type of the file

</file>

-------------------------                

------------------------

------------------------

---------------------

</MAT>

Output structure

<MAT>

<doc type>pdf</doc type

<subnumber>1234</subnumber>

<id>45ABC<id>

<matno>ABCD</matno>

<file>  0..unbounded

<file_content>file1.pdf<file_name>     ----->byte array content of the first file

<file_id>2y7hsjsj</file_id>             -------------->unique id of the first file

<file_type>pdf</file_type>         --------------->type of the file

</file>

<file>

<file_content>file2.xml<file_name>   ------------->byte array content of the second file

<file_id>8mnk9<file_id>               -----------------unique id of the second file

<file_type>xml</file_type>             ---------------------->type of the file

</file>

<file>

<file_content>file3.xml>                     ----------------->byte array content of the third file

<file_id>e783kj3k3</file_id          ---------------->unique id of the third  file

<file_type>xml<file_type>  --------------->type of the file

</file>

-------------------------                

------------------------

------------------------

---------------------

</MAT>

thx

mike

Former Member
0 Kudos

Hi Michael

Use the below code


package com.sap;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Result;

import javax.xml.transform.Source;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import com.sap.aii.mapping.api.AbstractTransformation;

import com.sap.aii.mapping.api.StreamTransformationException;

import com.sap.aii.mapping.api.TransformationInput;

import com.sap.aii.mapping.api.TransformationOutput;

public class populateTarget extends AbstractTransformation {

  public void transform(TransformationInput arg0, TransformationOutput arg1)

  throws StreamTransformationException {

  // TODO Auto-generated method stub

  this.execute(arg0.getInputPayload().getInputStream(), arg1

  .getOutputPayload().getOutputStream());

  }// end of transform

  public void execute(InputStream in, OutputStream out)

  throws StreamTransformationException {

  try {

  DocumentBuilderFactory tfactory = DocumentBuilderFactory

  .newInstance();

  DocumentBuilder tbuilder = tfactory.newDocumentBuilder();

  Document doc = tbuilder.parse(in);

  Document newdoc = tbuilder.newDocument();

  NodeList nlList = doc.getElementsByTagName("MAT"); // reading the

  // root node

  // from input

  // file

  Element root = (Element) nlList.item(0);

  // building the target structure

  Element target = newdoc.createElement("MAT");

  newdoc.appendChild(target);

  Element doctype = newdoc.createElement(root.getChildNodes().item(1)

  .getNodeName());

  doctype.setTextContent(root.getChildNodes().item(1)

  .getTextContent());

  target.appendChild(doctype);

  Element subnum = newdoc.createElement(root.getChildNodes().item(3)

  .getNodeName());

  subnum

  .setTextContent(root.getChildNodes().item(3)

  .getTextContent());

  target.appendChild(subnum);

  Element id = newdoc.createElement(root.getChildNodes().item(5)

  .getNodeName());

  id.setTextContent(root.getChildNodes().item(5).getTextContent());

  target.appendChild(id);

  Element matnum = newdoc.createElement(root.getChildNodes().item(7)

  .getNodeName());

  matnum

  .setTextContent(root.getChildNodes().item(7)

  .getTextContent());

  target.appendChild(matnum);

  // starting parsing all the file names

  NodeList filelist = doc.getElementsByTagName("file");

  for(int i =0; i < filelist.getLength();i++ )

  {

  Element filedata = newdoc.createElement("file");

  Element file = (Element) filelist.item(i);

  Element filecontent = newdoc.createElement("file_content");

  String filename = file.getChildNodes().item(1).getTextContent();

  // read the file from PI AL11 server and generate the byte content array

  byte[] fileArray = null;

  try {

  fileArray = getBytesFromFile(new File("C:\\"+filename)); // use actual path here

  } catch (IOException e) {

  e.printStackTrace();

  }

  String data = "";

  if (fileArray != null) {

  for (int k = 0; k < fileArray.length; k++) {

  data = data + fileArray[k];

  if (k < fileArray.length - 1) {

  data = data + ",";

  }

  }

  }

  filecontent.setTextContent("["+data+"]");

  filedata.appendChild(filecontent);

  Element file_id = newdoc.createElement("file_id");

  file_id.setTextContent(file.getChildNodes().item(3).getTextContent());

  filedata.appendChild(file_id);

  Element file_type = newdoc.createElement("file_type");

  file_type.setTextContent(file.getChildNodes().item(5).getTextContent());

  filedata.appendChild(file_type);

  target.appendChild(filedata);

  }

  Transformer transformer = TransformerFactory.newInstance()

  .newTransformer();

  Source source = new DOMSource(newdoc);

  Result output = new StreamResult(out);

  transformer.transform(source, output);

  } catch (Exception e) {

  e.printStackTrace();

  }

  } // end of execute

  // function to get bytes from a input file

  private static byte[] getBytesFromFile(File file) throws IOException {

  InputStream is = new FileInputStream(file);

  // Get the size of the file

  long length = file.length();

  /*

  * You cannot create an array using a long type. It needs to be an int

  * type. Before converting to an int type, check to ensure that file is

  * not loarger than Integer.MAX_VALUE;

  */

  if (length > Integer.MAX_VALUE) {

  System.out.println("File is too large to process");

  return null;

  }

  // Create the byte array to hold the data

  byte[] bytes = new byte[(int) length];

  // Read in the bytes

  int offset = 0;

  int numRead = 0;

  while ((offset < bytes.length)

  && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {

  offset += numRead;

  }

  // Ensure all the bytes have been read in

  if (offset < bytes.length) {

  throw new IOException("Could not completely read file "

  + file.getName());

  }

  is.close();

  return bytes;

  } // end of getBytesFromFile

}

The output would be like this

Former Member
0 Kudos

Thanks very much Indrajit. I am testing it and will let you know soon. you are great

mike

Former Member
0 Kudos

Great help Indrajit. Thanks again. It's working.

Answers (1)

Answers (1)

Former Member
0 Kudos

I believe this is a simple scenario. Nobody replying. I am losing hope here. Pls help

it has been pending for a week now..and I am not able to do this myself due to the beginner stage in java mapping

appreciate anyone helping on this

mike

Ryan-Crosby
Active Contributor
0 Kudos

Hi Mike,

First things first, what is your overall scenario?  Based on your input I am guessing synchronous SOAP -> PI -> ?  but not sure what your target is.  Also, if you are going to put binary data in the XML response then what is your encoding requirement for the consumer?

Regards,

Ryan Crosby

Former Member
0 Kudos

Hi Michael

Please find below the complete code


package com.sap;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Result;

import javax.xml.transform.Source;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import com.sap.aii.mapping.api.AbstractTransformation;

import com.sap.aii.mapping.api.StreamTransformationException;

import com.sap.aii.mapping.api.TransformationInput;

import com.sap.aii.mapping.api.TransformationOutput;

public class populateTarget extends AbstractTransformation {

  public void transform(TransformationInput arg0, TransformationOutput arg1)

  throws StreamTransformationException {

  // TODO Auto-generated method stub

  this.execute(arg0.getInputPayload().getInputStream(), arg1

  .getOutputPayload().getOutputStream());

  }// end of transform

  public void execute(InputStream in, OutputStream out)

  throws StreamTransformationException {

  try {

  DocumentBuilderFactory tfactory = DocumentBuilderFactory

  .newInstance();

  DocumentBuilder tbuilder = tfactory.newDocumentBuilder();

  Document doc = tbuilder.parse(in);

  Document newdoc = tbuilder.newDocument();

  NodeList nlList = doc.getElementsByTagName("MAT"); // reading the root node from input file

  Element root = (Element) nlList.item(0);

  // building the target structure

  Element target = newdoc.createElement("MAT");

  newdoc.appendChild(target);

  Element doctype = newdoc.createElement(root.getChildNodes().item(1)

  .getNodeName());

  doctype.setTextContent(root.getChildNodes().item(1)

  .getTextContent());

  target.appendChild(doctype);

  Element subnum = newdoc.createElement(root.getChildNodes().item(3)

  .getNodeName());

  subnum

  .setTextContent(root.getChildNodes().item(3)

  .getTextContent());

  target.appendChild(subnum);

  Element id = newdoc.createElement(root.getChildNodes().item(5)

  .getNodeName());

  id.setTextContent(root.getChildNodes().item(5).getTextContent());

  target.appendChild(id);

  Element matnum = newdoc.createElement(root.getChildNodes().item(7)

  .getNodeName());

  matnum

  .setTextContent(root.getChildNodes().item(7)

  .getTextContent());

  target.appendChild(matnum);

  Element filename = newdoc.createElement(root.getChildNodes()

  .item(9).getNodeName());

  filename.setTextContent(root.getChildNodes().item(9)

  .getTextContent());

  target.appendChild(filename);

  //adding the new field filecontent to the target xml structure

  Element filecontent = newdoc.createElement("filecontent");

           

  // reading file name from input file

  String filename1 = root.getChildNodes().item(9).getTextContent();

  // read the file from PI AL11 server and generate the byte content array

  byte[] fileArray = null;

  try {

  fileArray = getBytesFromFile(new File("/usr/sap"+filename1)); // use the actual Al11 path here

  } catch (IOException e) {

  e.printStackTrace();

  }

  String data = "";

  if (fileArray != null) {

  for (int i = 0; i < fileArray.length; i++) {

  data = data + fileArray[i];

  if (i < fileArray.length - 1) {

  data = data + ",";

  }

  }

  }

  filecontent.setTextContent(data);

  target.appendChild(filecontent); // adding byte content array to target xml

  Transformer transformer = TransformerFactory.newInstance()

  .newTransformer();

  Source source = new DOMSource(newdoc);

  Result output = new StreamResult(out);

  transformer.transform(source, output);

  } catch (Exception e) {

  e.printStackTrace();

  }

  } // end of execute

  // function to get bytes from a input file

  private static byte[] getBytesFromFile(File file) throws IOException {

  InputStream is = new FileInputStream(file);

  // Get the size of the file

  long length = file.length();

  /*

  * You cannot create an array using a long type. It needs to be an int

  * type. Before converting to an int type, check to ensure that file is

  * not loarger than Integer.MAX_VALUE;

  */

  if (length > Integer.MAX_VALUE) {

  System.out.println("File is too large to process");

  return null;

  }

  // Create the byte array to hold the data

  byte[] bytes = new byte[(int) length];

  // Read in the bytes

  int offset = 0;

  int numRead = 0;

  while ((offset < bytes.length)

  && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {

  offset += numRead;

  }

  // Ensure all the bytes have been read in

  if (offset < bytes.length) {

  throw new IOException("Could not completely read file "

  + file.getName());

  }

  is.close();

  return bytes;

  } //end of getBytesFromFile

}

Former Member
0 Kudos

Hi

The output would be like this

Former Member
0 Kudos

Great help!!! Indrajit. Really really appreciate you taking time to do this and I am definitely going to use your code. I will try this and let you know. There is a open bracket '[' and ']' closing bracked missing in the <filecontent> output generated by this java code.

In the meantime, one question. I wanted to do a HTTP POST ultimately and they are expecting like this (shown below) when they receive the POST request from PI.

Header and body. Header will be automatically generated by HTTP_AAE receiver adapter. Body is what I have to worry about I think.

/*header

POST /path/script.cgi HTTP/1.1
From: mike@mike.com
User-Agent: HTTPTool/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 32

*/body

doctype=pdf&subnumber=1234&id=45ABC&matno=ABCD&filename=transaction.pdf&filecontent=[116,104,105,115,32,116,101,115,116,32,102,105,108,101]

And also is there a easy way to do  HTTP POST to see how the actual result looks like?

thx a lot..

mike

Former Member
0 Kudos

Hi Michael

You can make a small change in java mapping to include braces ([ and ]).

For the HTTP post , check the document below

http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/80104882-c7a8-2f10-c3a3-81f182917...

It has the HTTP post example with the same format like your format.

Former Member
0 Kudos

Indrajit, thx again

So I believe, the java mapping has to be changed to not pass MAT for create element

// building the target structure   Element target = newdoc.createElement("MAT");  - I have to remove this

newdoc.appendChild(target);  - have to remove this.   Element doctype = newdoc.createElement(root.getChildNodes().item(1)  will be changed to item(0)

  .getNodeName()); 


And also to add the logic for  [    ]


String data = "["

if (fileArray != null) { 

for (int i = 0; i < fileArray.length; i++) { 

if data = "[";

data = data + fileArray[i]; 

else

if (i < fileArray.length - 1) { 

data = data + ","

endif.


data = data + "]";


is this right?


thx indrajit

-mike