cancel
Showing results for 
Search instead for 
Did you mean: 

SAX parser JAVA mapping issue in SAP PI 7.5 single stack but the same works in SAP PI 7.4 dual stack

SushantShinde
Advisor
Advisor
0 Kudos

Hello Experts,

can you please help me with the below issue. I have check the SAP XML toolkit checkbox in opeation mapping.

attaching the code as well for reference

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;


import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;


import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.DynamicConfiguration;
import com.sap.aii.mapping.api.DynamicConfigurationKey;
import com.sap.aii.mapping.api.StreamTransformation;
import com.sap.aii.mapping.api.StreamTransformationConstants;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;
/**
 * Converts XML input to flat csv file. According to defined CsvRecordSchema,
 * each <code><Record></code> element will be enriched with information from
 * parent <code><Rolle></code> element and written to csv output. In addition a
 * fileName is being computed and forwarded via the XI parameters map
 */




public class OcdBillInfoCsvMapper extends DefaultHandler implements StreamTransformation {
	  
/*	 public void transform(TransformationInput in,TransformationOutput out) throws StreamTransformationException{
	  InputStream instream = in.getInputPayload().getInputStream();
	  OutputStream outstream = out.getOutputPayload().getOutputStream();
	  Handling handler= new Handling();
	  SAXParserFactory factory = SAXParserFactory.newInstance();
	  String result=null;
	   try{
	      SAXParser saxpr = factory.newSAXParser(); 
	      saxpr.parse(instream,handler);
	      }
	     catch(Exception e){e.printStackTrace();}
	     
	     handler.execute(instream, outstream);
	     try{
	     out.getOutputPayload().getOutputStream().write(result.getBytes());
	      }
	  catch(IOException e){}
	   }
}




@SuppressWarnings("deprecation")
 class Handling extends DefaultHandler implements StreamTransformation
{
*/
	private static final String ROLE = "Rolle";
	private static final String RECORD = "Record";
	private static final String FIELD_SEPARATOR = "|"; // record separator for
	// csv file
	private static final String LINE_SEPARATOR = System.getProperty("line.separator"); 
	
	
	/** CsvRecordSchema, describes mapping from XML to CSV */
	private static final String[] CsvRecordSchema = { "RollenID",
			"ORIG_PERIOD", "RecordID", "RM_INSTANZ_ID", "RM_DATA_ID",
			"RecordNr", "SubRecordNr", "SplitNr", "Month", "Period", "LA",
			"Status", "PostType", "PostStatus", "Send_ARE", "BELNR_EXT",
			"POSNR_EXT", "ENDBETRAG", "FOLGE_BELEGNR", "FOLGE_POSNR",
			"FOLGE_BETRAG", "BUCH_DAT", "FAKT_INVOICE", "FAKT_POSNR",
			"FAKT_BETRAG", "FAKT_BUCH_DAT", "STORNO_BELEG", "PreisEinh" };
	private static final String OcdBillinfoCSVMapper = null;


	/** Record map, stores record data */
	private HashMap record;


	/** Role map, stores role data */
	private HashMap role;


	/** Current processing XML Element */
	private String currentElement;


	/** fileName for output csv */
	protected String fileName;


	/** Parameters of PI environment. */
	protected Map xiParameters = null;


	private boolean isData = false;


	private boolean isRecord = false;


	private Writer writer = null; // Ouput writer


	/**
	 * Constructor.
	 * @return 
	 */
	public void OcdBillInfoCsvMapper()
	{
	}
	
	// --- StreamTransformation Interface -------------------------------------


	/**
	 * Maps XML input file to flat file format.
	 * 
	 * @param in
	 *            XML file with role/record structure
	 * @param out
	 *            flat file output (UTF-8 with EOLN)
	 */
	public void execute(InputStream in, OutputStream out) 
		throws StreamTransformationException
	{
		try
		{
			// build the maps
			record = new HashMap(CsvRecordSchema.length);
			role = new HashMap(3);


			// Get a reader for input XML
			InputStreamReader isr = new InputStreamReader(in, "UTF-8");
			BufferedReader reader = new BufferedReader(isr, 8192);


			// Get a writer for output
			OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
			writer = new BufferedWriter(osw, 8192);


			// Get a SAX Parser
			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
			InputSource input = new InputSource(reader);
			// Parse input using this as handler
			parser.parse(input, this);


			writer.flush();
			
			if (fileName == null)
			{
				// first record finished, building filename
				String roleId = (String) role.get("RollenID");
				String period = (String) record.get("Period");
				String timeSent = (String) xiParameters
						.get(StreamTransformationConstants.TIME_SENT);
				fileName = XslSubstring(roleId, 1, 3) + "."
						+ XslSubstring(period, 1, 4)
						+ XslSubstring(period, 6, 2) + "."
						+ XslSubstring(timeSent, 12, 8).replaceAll(":", "")
						+ "..bill";
			}


			// Writing filename attributes
			setDynamicValue(xiParameters, "http://sap.com/xi/XI/System/File",
					"FileName", fileName, xiParameters
							.get(StreamTransformationConstants.MAPPING_TRACE));
		}
		catch (Exception ex)
		{
			Throwable inner = null;
			inner = ex;
			while (inner.getCause() != null)
				inner = inner.getCause();
			throw new StreamTransformationException(inner.getClass().getName()
					+ ' ' + inner.getMessage(), ex);
		}
	}


	/**
	 * StreamTransformation interface: set mapping parameters
	 */
	public void setParameter(Map params) {
	
		xiParameters = params;
		
	}


	// --- SAX Default Handler Implementation ----------------------------------
	/**
	 * Start XML element. <code><Rolle></code> and <code><Record></code>
	 * elements are being evaluated for state updates. All other elements
	 * contain data.
	 * 
	 * @param namespaceURI
	 *            XML namespace of element
	 * @param localName
	 *            local name of element (no namespace)
	 * @param qName
	 *            qualified name of element (with namespace prefix)
	 * @param atts
	 *            attributes of element
	 */
	public void startElement(String namespaceURI, String localName,
			String qName, Attributes atts) throws SAXException
	{
		// store current Element name
		currentElement = localName;
		if (localName.equals(ROLE))
		{
			// new role started
			isRecord = false;
		}
		else if (localName.equals(RECORD))
		{
			// new record started
			isRecord = true;


			// filename is built after first record has been processed
			if (fileName != null) try
			{
				// write line break before writing next record
				writer.write(LINE_SEPARATOR);
			}
			catch (IOException e)
			{
				throw new SAXException(e);
			}
		}
		else isData = true;
	}


	/**
	 * Handles text of XML element.
	 * 
	 * @param ch
	 *            char content of element
	 * @param start
	 *            begin of content
	 * @param length
	 *            length of content
	 */
	public void characters(char[] ch, int start, int length)
			throws SAXException
	{
		// check if we have a element which contains data and store data with
		// key of current element
		if (isData) if (!isRecord) // role data
				role.put(currentElement, new String(ch, start, length));
			else if (isRecord) // record data
				record.put(currentElement, new String(ch, start, length));


	}


	/**
	 * End of XML element.
	 * 
	 * @param namespaceURI
	 *            XML namespace of element
	 * @param localName
	 *            local name of element (no namespace)
	 * @param qName
	 *            qualified name of element (with namespace prefix)
	 */
	public void endElement(String namespaceURI, String localName, String qName)
			throws SAXException
	{
		if (localName.equals(RECORD))
		{
			// record is closed
			isRecord = false;


			// checking if filename has already been built
			if (fileName == null)
			{
				// first record finished, building filename
				String roleId = (String) role.get("RollenID");
				String period = (String) record.get("Period");
				String timeSent = (String) xiParameters
						.get(StreamTransformationConstants.TIME_SENT);
				fileName = XslSubstring(roleId, 1, 3) + "."
						+ XslSubstring(period, 1, 4)
						+ XslSubstring(period, 6, 2) + "."
						+ XslSubstring(timeSent, 12, 8).replaceAll(":", "")
						+ "..bill";
			}
			


			// write the CSV record
			try
			{
				writeCsvRecord(writer);
			}
			catch (Exception e)
			{
				throw new SAXException(e);
			}


		}
		else if (localName.equals(ROLE))
		{
			// Role is closed, cleaning role data
			isRecord = false;
			role.clear();
		}
		else isData = false;
	}


	/**
	 * Java implementation of XPath substring function. Some special conversions
	 * must be applied for the XPath version.
	 * 
	 * @param content
	 *            String content which will substringed
	 * @param i
	 *            Start index for substring
	 * @param j
	 *            Length for substring
	 * @return resulting substring
	 */
	private String XslSubstring(String content, int i, int j)
	{
		if (content == null) return "";
		if (i <= 0)
		{
			// xpath substring allows negativ start index, converting to "java"
			// index
			j = i - 1 + j;
			i = 1;
			if (j <= 0) return "";
		}


		// Xslt substring function starts with index 1 and stops after j characters
		i--;


		if (content.length() > i && content.length() >= i + j)
			return content.substring(i, j+i);
		else if (content.length() > i)
			return content.substring(i);
		else return "";
	}


	/**
	 * /** Set value in DynamicConfiguration. The value will be set using
	 * parameter <code>pParams</code> which must be the XSLT stylesheet
	 * <code>inputparam</code> parameter filled by PI with the configuration
	 * map. If called from a Java mapping <code>pParam</code> must be the
	 * paramter map provided to the mapping by PI via method
	 * <code>setParameters</code>. If <code>pParams</code> is null or not an
	 * instance of <code>Map</code>, it is assumed that the calling mapping is
	 * not executed inside PI. In this case the value will not be stored.
	 * 
	 * @param pParams
	 *            input parameters provided by PI to each stylesheet
	 * @param pNamespace
	 *            namespace of configuration item
	 * @param pKey
	 *            key of configuration item
	 * @param pValue
	 *            value for key
	 */
	@SuppressWarnings("null")
	public String setDynamicValue(Object pParams, String pNamespace,
			String pKey, String pValue, Object pTrace)
	{
		TraceWrapper trace = new TraceWrapper(pTrace);
			
		// Check dynamic configuration
		if (pParams == null)
		{
			trace.addInfo("No XI parameters set. Value will not be stored.");
			return "NOT-STORED";
		}
		if (!Map.class.isInstance(pParams))
		{
			trace.addInfo("XI paramters no instance of Map. Value will not be stored.");
			return "NOT-STORED";
		}
		
		trace.addInfo("appending values to xiParameters");
		Map xiParameters = (Map) pParams;
		
		trace.addInfo("Values" + xiParameters);
		DynamicConfiguration conf = (DynamicConfiguration) xiParameters
				.get("DynamicConfiguration");
		
		trace.addInfo("conf parameter is captured is done");
		
		if (conf == null)
		{
			trace.addInfo("No DynamicConfiguration in XI parameters map. Value will not be stored.");
			return "NOT-STORED";
		}


		DynamicConfigurationKey key = DynamicConfigurationKey.create(
				pNamespace, pKey);
		trace.addInfo("Key::::" + key);
		trace.addInfo("pValue:::" + pValue);
		conf.put(key, pValue);
		trace.addInfo("DC Value:::" + pValue);
		return "DONE";
	}


	/** Write line to output. */
	void writeCsvRecord(Writer writer) throws IOException
	{
		// put role data into record data to ease map-access
		record.putAll(role);


		// iterate schema mapping
		for (int i = 0; i < CsvRecordSchema.length; i++)
		{
			// get data and remove it from map
			String field = (String) record.remove(CsvRecordSchema[i]);
			if (field != null)
			{
				// look for special date-conversion for field "FAKT_BUCH_DAT"
				if (CsvRecordSchema[i].equals("FAKT_BUCH_DAT"))
					field = field.replaceAll("-", "");


				// write CSV data
				writer.write(field);
			}


			if (i < CsvRecordSchema.length - 1) writer.write(FIELD_SEPARATOR); // write separator
		}
		writer.flush();
	}


	
	public static void main(String []args) {
		
		try {
			FileInputStream in = new FileInputStream("C:\\Users\\i355261\\Desktop\\ATOS\\JAVA_Mapping\\SampleSource Data.xml");
			FileOutputStream out = new FileOutputStream("C:\\Users\\i355261\\Desktop\\ATOS\\JAVA_Mapping\\Output.xml");
			
			OcdBillInfoCsvMapper instance = new OcdBillInfoCsvMapper();
			instance.execute(in, out);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (StreamTransformationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


}


  • Loaded class com.siemens.sis.ocd.mediation.OcdBillInfoCsvMapper
  • Call method execute of the application Java mapping com.siemens.sis.ocd.mediation.OcdBillInfoCsvMapper
  • Loaded class com.siemens.sis.ocd.mediation.TraceWrapper
  • *** START APPLICATION TRACE ***
  • appending values to xiParameters
  • Values{InputAttachments=null, ConversationId=, Profiling=off, SenderName=, ProcessingMode=, OutputAttachments=null, VersionMajor=, InterfaceNamespace=, SenderPartyAgency=, RefToMessageId=, DynamicConfiguration=<DynamicConfiguration></DynamicConfiguration>, ReceiverService=Test_ReceiverService, ReceiverPartyScheme=, ReceiverParty=Test_ReceiverParty, SenderNamespace=, SenderSystem=Test_SenderSystem, TimeSent=, SenderService=Test_SenderService, SenderPartyScheme=, ReceiverSystem=Test_ReceiverSystem, VersionMinor=, ReceiverPartyAgency=, ReceiverNamespace=, ReceiverName=, Interface=, SenderParty=Test_SenderParty, MappingTrace=Loaded class com.siemens.sis.ocd.mediation.OcdBillInfoCsvMapper Call method execute of the application Java mapping com.siemens.sis.ocd.mediation.OcdBillInfoCsvMapper Loaded class com.siemens.sis.ocd.mediation.TraceWrapper *** START APPLICATION TRACE *** appending values to xiParameters , MessageId=}
  • conf parameter is captured is done
  • Key::::<namespace>http://sap.com/xi/XI/System/File</namespace><name>FileName</name>
  • *** END APPLICATION TRACE ***
  • Java mapping com/siemens/sis/ocd/mediation/OcdBillInfoCsvMapper has thrown a StreamTransformationException.
  • com.sap.aii.mapping.api.StreamTransformationException: java.lang.IllegalArgumentException Values in a DynamicConfiguration must not be null. at com.siemens.sis.ocd.mediation.OcdBillInfoCsvMapper.execute(OcdBillInfoCsvMapper.java:154) at com.sap.aii.ib.server.mapping.execution.TransformationWrapper.transform(TransformationWrapper.java:39) at com.sap.aii.ib.server.mapping.execution.JavaMapping.executeStep(JavaMapping.java:112) at com.sap.aii.ib.server.mapping.execution.Mapping.execute(Mapping.java:60) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:87) at com.sap.aii.ib.server.mapping.execution.MappingHandler.map(MappingHandler.java:54) at com.sap.aii.ibrep.server.mapping.rt.MappingHandlerAdapter.run(MappingHandlerAdapter.java:139) at com.sap.aii.ibrep.server.mapping.exec.ExecuteIfMapCommand.execute(ExecuteIfMapCommand.java:33) at com.sap.aii.ib.server.mapping.exec.CommandManager.execute(CommandManager.java:43) at com.sap.aii.ibrep.server.mapping.ServerMapService.execute(ServerMapService.java:40) at com.sap.aii.ibrep.server.mapping.MapServiceBean.execute(MapServiceBean.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:47) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:50) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.doWorkWithAttribute(Interceptors_Transaction.java:37) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.invoke(Interceptors_Transaction.java:21) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_MethodRetry.invoke(Interceptors_MethodRetry.java:46)

19:38:11 End of test

BR,

Sushant

Accepted Solutions (1)

Accepted Solutions (1)

SushantShinde
Advisor
Advisor
0 Kudos

Hello All,

Since Java 8 as we have in SAP PI 7.5, for execution of SAX parser we need add the below code while declaring the SAX parser factory

the code that needs to be added while declaring the SAX parser

factory.setNamespaceAware(true);

Till Java 6, this set of code was default initialized as true and didn't needed declaration, but since Java 8 and PI 7.5, we need to declare it to get the SAX parser working.

Regards,

Answers (0)