XPathReplacementBean – Modify XML payload statically or dynamically at module layer

Background:

Migrate from old B2B integration platform to SAP Process Orchestration using B2B add-on for all Ansi x12 EDI transmissions.

 

Problem Statement:

In old platform, the system allowed for the maintenance of n number of IDs for any possibly qualifier, e.g. ZZ.  When we were initially migrating the new system also allowed this, but would overwrite any data saved to the party in the integration directory with only the last entry saved in the Trading Partner Management.  What we discovered was that any 997 transmissions would only work for the last ZZ qualifier ID that was saved which usually meant only one of our many external partners.  Since our old system allowed for n number of IDs we generally had one unique ID for each separate trading partner.  How do we limit ourselves to one ID for qualifier ZZ without asking our external partners to modify their configurations?

 

Workaround:

Can I add two IDs with the same qualifier into the system for our self-party?

Adjust the text for the agency scheme as seen below so all the values would save in the integration directory for the self-party – i.e. put some unique number at the end.

The result in Integration Directory after adjusting the scheme text.

Do I get any side effects in the system by adjusting this text?  I don’t really want to find out the hard way.

 

Alternative: A custom adapter module which will target specific segments of the XML payload and overwrite the value needed for TPMContentAccessModule with the value required by our external partner.

 

Code:

/* * Created: August 3rd, 2015 * @author Ryan Crosby */ package com.yourorganization.utils.xml; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Enumeration; import javax.ejb.Stateless; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.sap.aii.af.lib.mp.module.Module; import com.sap.aii.af.lib.mp.module.ModuleContext; import com.sap.aii.af.lib.mp.module.ModuleData; import com.sap.aii.af.lib.mp.module.ModuleException; import com.sap.engine.interfaces.messaging.api.Message; import com.sap.engine.interfaces.messaging.api.MessageKey; import com.sap.engine.interfaces.messaging.api.MessagePropertyKey; import com.sap.engine.interfaces.messaging.api.PublicAPIAccess; import com.sap.engine.interfaces.messaging.api.PublicAPIAccessFactory; import com.sap.engine.interfaces.messaging.api.XMLPayload; import com.sap.engine.interfaces.messaging.api.auditlog.AuditAccess; import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus; import com.sap.engine.interfaces.messaging.api.exception.InvalidParamException; import com.sap.engine.interfaces.messaging.api.exception.MessagingException; @Stateless public class XPathReplacementBean implements SessionBean, Module{ /** * */ private static final long serialVersionUID = -2801247541078166093L; private MessageKey amk; private AuditAccess audit; private Message msg; @Override public ModuleData process(ModuleContext mc, ModuleData md) throws ModuleException { // Get message data and audit access msg = (Message) md.getPrincipalData(); XMLPayload payload = msg.getDocument(); amk = new MessageKey(msg.getMessageId(), msg.getMessageDirection()); PublicAPIAccess pa; try { pa = PublicAPIAccessFactory.getPublicAPIAccess(); } catch (MessagingException e) { throw new ModuleException(e.getMessage()); } audit = pa.getAuditAccess(); // Get full list of keys Enumeration e = mc.getContextDataKeys(); ArrayList

 

Notes & Final Thoughts:

  • If you have ever used the SeeBurger adapter modules before you will notice I built it with the intention that new functions could be added as required since it uses reflection.
  • For the purposes of simplicity in the use of reflection I have set it up to expect only String types for parameters and return values with any type casting handled internally within the methods.
  • I wanted to share this alternative in the event that it may help others when they are facing a situation where there hands may be tied and it would help to avoid creating additional flows and other workaround solutions – specifically when you require something at the adapter level and it is something that cannot wait until receiver determination or within the mapping runtime.

New NetWeaver Information at SAP.com

Very Helpfull

User Rating: Be the first one !
Comments (0)
Add Comment