Today I'd like to share with you one of my favourite tricks, that is how to handle adapter modules in SOAP Sender Channels. As you may know, this is not officially supported by SAP, and you'll notice there are some limitations as long as you experiment with my code here below, but it usually works pretty good.
I won't waste any time in long and useless descriptions here, as the real heart of the thing is the code itself, while you can a find a whole bunch of doc, blogs and wikis on the modules matter itself. Just be aware that the code below is for PI 7.1x (though it can be easily backported to 3.0 / 7.0) and that you can safely take it as the main skeleton for any module implementation (SOAP sender as well, yes).
I have devolped this tiny thing using in a DC with NWDI and I am pretty sure you need to add a a few more dependency to exploit the classes that are needed to handle the SOAP Sender romance, but now I honestly don't remember so I'll just put a couple of screenshot of my Java Build Path libs and Used DCs, from which it should be pretty easy to guess what's missing in your project compared to a common PI Adapter Module one.
Enjoy.
| /** * */ package org.guarneri.sap.pi; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.rmi.RemoteException; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; 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.aii.af.sdk.xi.lang.Binary; import com.sap.aii.af.sdk.xi.mo.DefaultItem; import com.sap.aii.af.sdk.xi.mo.MessageContext; import com.sap.aii.af.service.administration.api.cpa.CPAFactory; import com.sap.aii.af.service.administration.api.cpa.CPALookupManager; import com.sap.aii.af.service.cpa.Binding; import com.sap.engine.interfaces.messaging.api.Message; // import com.sap.aii.adapter.xi.ms.XIMessage; import com.sap.engine.interfaces.messaging.api.MessageDirection; import com.sap.engine.interfaces.messaging.api.MessageKey; import com.sap.engine.interfaces.messaging.api.PublicAPIAccess; import com.sap.engine.interfaces.messaging.api.PublicAPIAccessFactory; import com.sap.engine.interfaces.messaging.api.auditlog.AuditAccess; import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus; import com.sap.tc.logging.Location; import com.sap.tc.logging.MsgObject; import com.sun.org.apache.xml.internal.serialize.OutputFormat; import com.sun.org.apache.xml.internal.serialize.XMLSerializer; /** * @author Ale * */ public class SOAPSenderAlsoBean implements SessionBean, Module { final String SIG = "SOAPSenderAlsoBean - "; MessageKey key = null; PublicAPIAccess pa; AuditAccess audit; Message msg1; com.sap.aii.af.sdk.xi.mo.Message msg2; DefaultItem defaultItem; boolean commonMessage; boolean xmlDeclaration = true; private Location loc = null; public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData) throws ModuleException { loc = Location.getLocation(SOAPSenderAlsoBean.class.getName()); loc.entering(SIG, new Object[] { moduleContext, inputModuleData }); // Recognizing Adapter type String adapterType = null; try { String chid = moduleContext.getChannelID(); CPALookupManager lm = CPAFactory.getInstance().getLookupManager(); Binding b = lm.getBindingByChannelId(chid); adapterType = b.getAdapterType(); } catch (Exception e) { throw new ModuleException( "Couldn't recognize Adapter Type due to: " + e.getMessage(), e); } // Handle usual basic stuff: get the Message and the Audit instance InputStream is = null; Object obj = inputModuleData.getPrincipalData(); if (obj instanceof com.sap.aii.af.sdk.xi.mo.MessageContext) { commonMessage = false; MessageContext principalData = (MessageContext) obj; msg2 = principalData.getMessage(); } else { commonMessage = true; msg1 = (Message) inputModuleData.getPrincipalData(); is = msg1.getDocument().getInputStream(); } if (!commonMessage) { // SOAP Sender defaultItem = (DefaultItem) msg2.getBodyItems().nextElement(); try { Binary bin = defaultItem.getDataAsBinary(); is = new ByteArrayInputStream(bin.getBytes()); } catch (Exception e) { loc.error("", new MsgObject("001", "Error getting SOAP sender Request message: " + e.getMessage())); } } try { if (commonMessage) { if (msg1.getMessageDirection() == MessageDirection.OUTBOUND) key = new MessageKey(msg1.getMessageId(), MessageDirection.OUTBOUND); else key = new MessageKey(msg1.getMessageId(), MessageDirection.INBOUND); } else { key = (MessageKey) inputModuleData .getSupplementalData("audit.key"); // SOAP Sender } pa = PublicAPIAccessFactory.getPublicAPIAccess(); audit = pa.getAuditAccess(); } catch (Exception e) { throw new ModuleException("Error creating basic instances: " + e.getMessage() + getStackTrace(e), e); } audit.addAuditLogEntry(key, AuditLogStatus.SUCCESS, SIG + "Process started - Adapter type: " + adapterType); // ---------------------------------------------------------- // Get module parameters // ---------------------------------------------------------- String p1 = moduleContext.getContextData("p1"); String p2 = moduleContext.getContextData("p2"); // ... // ---------------------------------------------------------- // Parse input document // ---------------------------------------------------------- Document d; try { d = parseDoc(is); } catch (Exception e) { throw new ModuleException(SIG + "Error while parsing and normalizing main document: " + e.getMessage() + getStackTrace(e), e); } audit.addAuditLogEntry(key, AuditLogStatus.SUCCESS, SIG + "Document implementation is " + d.getClass().getName()); // ---------------------------------------------------------- // Do THE Module's JOB! // ---------------------------------------------------------- // ... // ---------------------------------------------------------- // Finalize process by setting new payload // ---------------------------------------------------------- try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLSerializer xs = new XMLSerializer(); OutputFormat of = new OutputFormat(d, "UTF-8", false); xs.setOutputFormat(of); xs.setOutputByteStream(baos); xs.serialize(d); if (commonMessage) { msg1.getDocument().setContent(baos.toByteArray()); inputModuleData.setPrincipalData(msg1); } else { defaultItem.setData(new Binary(baos.toByteArray())); } } catch (Exception e) { throw new ModuleException(SIG + "Error while setting new payload: " + e.getMessage() + getStackTrace(e), e); } audit.addAuditLogEntry(key, AuditLogStatus.SUCCESS, SIG + "Process ended"); return inputModuleData; } public Document parseDoc(InputStream is) throws ModuleException { try { DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document d = builder.parse(is); return d; } catch (Exception e) { throw new ModuleException(SIG + "Error parsing document" + e.getMessage() + getStackTrace(e), e); } } public String getStackTrace(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); t.printStackTrace(pw); pw.flush(); sw.flush(); return sw.toString(); } public void ejbActivate() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws EJBException, RemoteException { } public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException { } public void ejbCreate() throws javax.ejb.CreateException { } } |
| Java2html |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 525 | |
| 263 | |
| 238 | |
| 234 | |
| 167 | |
| 157 | |
| 152 |