If you’ve ever worked with adapter modules in SAP NetWeaver PI, then you already know how powerful they can be when it comes to enhancing the functionality of Java-based adapters. In this blog, I’ll show you how adapter modules can be used to dynamically derive the queue ID (also referred to as the sequence ID) for EOIO message processing.
For those of you that may not be familiar with adapter modules, a brief introduction is in order. In many respects, you can think of an adapter module as a type of user exit that can be used to enhance the functionality of a Java-based adapter. From a technical perspective, adapter modules are implemented as a stateless session Enterprise JavaBean (EJB). Here, in addition to implementing the typical javax.ejb.SessionBean interface, adapter modules must also implement the com.sap.aii.af.lib.mp.module.Module interface prescribed by SAP. Such standardization makes it possible to seamlessly interject adapter modules into the processing sequence for adapters. On the development side of things, you’re simply tasked with implementing the process() method defined by the Module interface.
If all this seems a little hazy, then an excellent resource is William Li’s article Developing Adapter User-Module to Encrypt XML Elements in Process Integration 7.1. There, you will find a step-by-step introduction to adapter modules, their development, deployment, etc. For now, we’ll assume that the basic framework is in place and move on to take a look at the Java code required to perform the dynamic queue derivation.
Dynamic Queue Derivation
As you’re probably already aware, the term EOIO stands for Exactly Once In Order. In terms of message processing, what we’re saying is that each incoming message should be processed exactly once, and in the order that it is received. To guarantee sequencing, messages are serialized through FIFO queues (where FIFO stands for “First In, First Out”).
The problem with many Java-based adapters is that the queue names are statically assigned at configuration time instead of at runtime. For example, in the screenshot below, you can see how a JMS sender channel is configured for EOIO processing. In this case, the queue name is statically defined at configuration time within the Integration Directory. In some cases, this may not be granular enough for your use case. For instance, you may want to derive the EOIO queue names in terms of some key identifier in the inbound message (e.g. a document number).
To get around this limitation, you can write an adapter module to override the queue ID value at runtime. The code itself is surprisingly simple:
public class MyAdapterModule implements SessionBean, Module
public ModuleData process(ModuleContext moduleCtx, ModuleData moduleData)
// Extract the input message from the module data:
Message msg = (Message) moduleData.getPrincipalData();
// Use the Message instance to parse the incoming XML;
// For example, if the incoming message is a sales order,
// then we might derive the queue ID using the sale order number:
// String queueId = “”;
// Once the queue ID is derived, set it using the setSequenceId()
catch (Exception ex)
// Exception handling goes here…
Looking at the code above, you can see that the only thing required to dynamically set the queue ID is a call to the setSequenceId() method defined in interface com.sap.engine.interfaces.messaging.api.Message. The queue ID itself can be derived based upon the content of the incoming message. For example, we could write a SAX handler class to quickly parse through the incoming message looking for a document number or some other key identifier that helps us derive the seqeunce for EOIO message processing.
Once the adapter module is complete and deployed on the AS Java, you can interject it into the processing seqeunce for a sender channel like the OrderMessageRouterBean shown below. That’s all there is to it.
While this technique is powerful, you should be careful not to add too much additional overhead to your process. If you’re familiar with SAX-based XML parsing, then I highly recommend that you use it to keep the memory footprint low and reduce the overall runtime.