Skip to Content

Archived discussions are read-only. Learn more about SAP Q&A

Java mapping runtime issue

Hi,

I have currently created a java mapping which unzips files and transforms plain text/falt files to xml according to a specific structure... So far so good. This stuff works perfectly when testing interface mapping in the repository. However at runtime it does not work, and this is where you clever guys come into the picture:-)

It should be mentioned that the zip-file is dropped on a MQ-queue and picked up in XI and passed on to a BPM - the only thing the BPM does is to perform the java mapping and afterwards send one of the messages to R/3 and the other to CRM.

The concrete error given at runtime in the PE is:

Error handling for work item 000000718016

Work item 000000718016: Object CL_SWF_XI_MSG_BROKER method CALL_TRANSFORMATION cannot be executed

Parsing error before mapping: unexpected end-of-file (line 1, column 1)

Hope somone can help me on this matter,

Best regards,

Daniel

PS: In case it is of interest/use the java code used is this:

package dk.post.xi.unzipAndConvert;

import java.io.*;

import java.util.Map;

import java.util.HashMap;

import java.util.zip.ZipEntry;

import java.util.zip.ZipInputStream;

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

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

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

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

public class UnzipMain implements StreamTransformation {

private MappingTrace mappingTrace = null;

private Map param = null;

private StringBuffer currentXmlRecord = new StringBuffer();

private StringBuffer currentPlainRecord = new StringBuffer();

private int[][] dataRanges = null;

private char[] charsInCurrentRange = new char[650];

private String[] xmlTagNames = null;

/* (non-Javadoc)

  • @see com.sap.aii.mapping.api.StreamTransformation#setParameter(java.util.Map)

  • Method must be implemented when class is implementing streamTransformation

*/

public void setParameter(Map param) {

this.param = param;

if (param == null) {

this.param = new HashMap();

}

}

/*

  • (non-Javadoc)

  • @see com.sap.aii.mapping.api.StreamTransformation#execute(java.io.InputStream, java.io.OutputStream)

  • Main function -- called by XI to start execution of java mapping

*/

public final void execute(InputStream in, OutputStream out)

throws StreamTransformationException

{

//if no input, then cancel program execution

if (in == null) {

throw new RuntimeException("Something wrong with input zip file - is null");

}

//input <> null. Begin upzip operation

try {

//test is only relevant outside of XI

if (param != null) {

mappingTrace = (MappingTrace) param.get(StreamTransformationConstants.MAPPING_TRACE );

}

ZipInputStream zip = null;

try {

zip = new ZipInputStream(in);

ZipEntry ze = null;

out.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><ns0:Messages xmlns:ns0=\"http://sap.com/xi/XI/SplitAndMerge\">".getBytes());

while ((ze = zip.getNextEntry()) != null) {

writeDebugInfo("File: " + ze.getName() + " with compressed size: " + ze.getCompressedSize());

scrutinize(zip,(ZipEntry) ze, out);

}

out.write("</ns0:Messages>".getBytes());

}

finally {

if (zip != null)

zip.close();

out.flush();

out.close();

}

} catch (Exception e) {

throw new RuntimeException(e + "\nSomething went wrong...");

}

}

//Unzip flat files and convert to xml

private void scrutinize(ZipInputStream inStream,ZipEntry zipEntry, OutputStream outstream) throws Exception {

long start = System.currentTimeMillis();

InputStreamReader inStreamReader = null;

BufferedReader buffReader = null;

byte[] xmlBytes = null;

try {

inStreamReader = new InputStreamReader(inStream);

buffReader = new BufferedReader(inStreamReader);

boolean masterData = zipEntry.getName().equals("PD-01-STAMDATA.DAT");

boolean creditData = zipEntry.getName().equals("PD-02-KREDITVURDERING.DAT");

String currentLine = null;

if (masterData) {

writeDebugInfo("- Begin reading and converting every line of MasterData..."); //out-comment this outside of XI, or compilation will fail (functionality is only available in XI)

outstream.write("<ns0:Message1><ns1:masterData_MT xmlns:ns1=\"http://pdk/xi/kob/importDataToSap\">".getBytes());

while ((currentLine = buffReader.readLine()) != null) {

//convert one line of credit data plain into an xml record structure

makeXmlRecord(currentLine,true);

//Write record XML to XI's outputstream (appends)

xmlBytes = currentXmlRecord.toString().getBytes();

outstream.write(xmlBytes);

}

outstream.write("</ns1:masterData_MT></ns0:Message1>".getBytes());

writeDebugInfo("- Finished reading and converting every line of MasterData..."); //out-comment this outside of XI, or compilation will fail (functionality is only available in XI)

}

if (creditData) {

writeDebugInfo("- Begin reading and converting every line of CreditData...");

outstream.write("<ns0:Message2><ns1:creditData_MT xmlns:ns1=\"http://pdk/xi/kob/importDataToSap\">".getBytes());

while ((currentLine = buffReader.readLine()) != null) {

//convert one line of credit data plain into an xml record structure

makeXmlRecord(currentLine,false);

//Write record XML to XI's outputstream (appends)

xmlBytes = currentXmlRecord.toString().getBytes();

outstream.write(xmlBytes);

}

outstream.write("</ns1:creditData_MT></ns0:Message2>".getBytes());

writeDebugInfo("- Finished reading and converting every line of CreditData...");

}

} finally {

long timeUsed = System.currentTimeMillis() - start;

writeDebugInfo(zipEntry.getName() + " - Write took: " + timeUsed + " ms");

writeDebugInfo("Final statement entered...\n");

}

}

//check for invalid xml chars (plus a few other strange chars) in a plain text record and if any are found update the ranges of so they correspond to the new length of a record

private int[][] checkRange(String currentPlainLine, boolean isMasterData) {

int counter = 0;

int beginRange = 0;

int endRange = 0;

//populate array with proper data ranges/intervals according to how data is to be split

dataRanges = isMasterData ? new int[][] {{0,2},{2,12},{12,44},{44,47},{47,50},{50,295},{295,298},{298,356},{356,426},{426,496},{496,499},{499,506},{506,510},{510,518},{518,540},{540,546},{546,552},{552,558},{558,564},{564,570},{570,576},{576,582},{582,588},{588,594},{594,604}} : new int[][] {{0,2},{2,12},{12,20},{20,23},{23,26},{26,29},{29,44}};

//ensure stringbuffer is empty

currentPlainRecord.delete(0,currentPlainRecord.length());

//insert the current plain text line into stringbuffer

currentPlainRecord.append(currentPlainLine);

//loop through outer array (array of ranges)

for (int i = 0; i <= (dataRanges.length-1); i++) {

beginRange = dataRanges<i>[0];

counter = beginRange;

endRange = dataRanges<i>[1];

//loop through stringbuffer, based on the value-pairs of ranges/intervals in array of arrays

while (counter < endRange) {

switch (currentPlainRecord.charAt(counter)) {

case '&':

currentPlainRecord.insert(counter+1,"amp;"); //insert 'amp;' after '&', so that syntax conforms to xml syntax requirements (&amp;)

counter += 5; //increment counter so that it continues after insertet characters

updateRange(counter,4); //update the array of ranges so that is corresponds to the new range

break;

case '\'':

currentPlainRecord.replace(counter,counter+1,"&"); //replace '\'' with '&'

currentPlainRecord.insert(counter+1,"apos;"); //insert 'apos;' after '\'', so that syntax conforms to xml syntax requirements (&apos;)

counter += 6; //increment counter so that it continues after insertet characters

updateRange(counter,5); //update the array of ranges so that is corresponds to the new range

break;

case '"':

currentPlainRecord.replace(counter,counter+1,"&"); //replace '"' with '&'

currentPlainRecord.insert(counter+1,"quot;"); //insert 'quot;' after '"', so that syntax conforms to xml syntax requirements (&quot;)

counter += 6; //increment counter so that it continues after insertet characters

updateRange(counter,5); //update the array of ranges so that is corresponds to the new range

break;

case '<':

currentPlainRecord.replace(counter,counter+1,"&"); //replace '<' with '&'

currentPlainRecord.insert(counter+1,"lt;"); //insert 'lt;' after '&', so that syntax conforms to xml syntax requirements (&lt;)

counter += 4; //increment counter so that it continues after insertet characters

updateRange(counter,3); //update the array of ranges so that is corresponds to the new range

break;

case '>':

currentPlainRecord.replace(counter,counter+1,"&"); //replace '>' with '&'

currentPlainRecord.insert(counter+1,"gt;"); //insert 'gt;' after '&', so that syntax conforms to xml syntax requirements (&gt;)

counter += 4; //increment counter so that it continues after insertet characters

updateRange(counter,3); //update the array of ranges so that is corresponds to the new range

break;

case 0x7F:

currentPlainRecord.replace(counter,counter+1," "); //replace 0x7F with ' '

writeDebugInfo("-- Corrected the character 0x7F ('') to ' '");

counter++;

break;

case '‘':

currentPlainRecord.replace(counter,counter+1," "); //replace 0x91 ('‘') with ' '

writeDebugInfo("-- Corrected the character '‘' to ' '");

counter++;

break;

case '›':

currentPlainRecord.replace(counter,counter+1," "); //replace 0x9B ('›') with ' '

writeDebugInfo("-- Corrected the character 0x9B to ' '"); counter++;

break;

case '†':

currentPlainRecord.replace(counter,counter+1," "); //replace '†' with ' '

writeDebugInfo("-- Corrected the character '†' to ' '");

counter++;

break;

default :

counter++;

break;

}

}

}

return dataRanges;

}

//update array of ranges so that is corresponds to the new range

private void updateRange(int currentRange, int updateRangeBy) {

for (int k = currentRange; k < dataRanges.length; k++) {

if (k != currentRange) { //never update begin interval for the current range - only for the remaining intervals

dataRanges[k][0] += updateRangeBy;

}

dataRanges[k][1] += updateRangeBy; //always update end intervals

}

}

//convert one flat record line to a xml record structure

private void makeXmlRecord(String currentPlainLine,boolean isMasterData) {

dataRanges = checkRange(currentPlainLine,isMasterData);

//clear StringBuffer

currentXmlRecord.delete(0,currentXmlRecord.length());

//get the correct set of xml tags to be used when performing mapping between plain text and xml

if (isMasterData) {

xmlTagNames = new String[] {"dum1","kob_no","dum2","corp_status","legal_form","dum3","pr_protec_code","dum4","uri","email","emp_no_grp_code","exact_no_emp","dum5","founding_date","dum6","main_industry_code","industry_code1","industry_code2","industry_code3","industry_code4","industry_code5","industry_code6","industry_code7","industry_code8","dum7"};

} else {

xmlTagNames = new String[] {"dum1","kob_no","rating_date","rating_value","risc_grp_code","currency","max_credit"};

}

//copy all chars in stringBuffer to the specified char[]

currentPlainRecord.getChars(0,currentPlainRecord.length(),charsInCurrentRange,0);

//populate XML record structure

currentXmlRecord.append("<record>");

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

currentXmlRecord.append("<" + xmlTagNames<i> + ">");

currentXmlRecord.append(charsInCurrentRange,dataRanges<i>[0],(dataRanges<i>[1])-(dataRanges<i>[0]));

currentXmlRecord.append("</" + xmlTagNames<i> + ">");

}

currentXmlRecord.append("</record>");

}

//write debug information to correct "place"

private void writeDebugInfo(String debugInfo) {

if (mappingTrace == null) {

System.out.println("Debug: " + debugInfo);

} else {

mappingTrace.addInfo("Debug: " + debugInfo);

}

}

}

Not what you were looking for? View more on this topic or Ask a question