Skip to Content

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.

Getting Started

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).

image

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)
    throws ModuleException
  {
    try
    {
      // 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()
      // method:
      msg.setSequenceId(queueId);
      moduleData.setPrincipalData(msg);

      return moduleData;
    }
    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.

image

Closing Thoughts

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.

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Vijayashankar Konam
    This is a good generic way of achieving this. How ever, for SOAP adapter this could be achieved using query string parameters as &QueueId= at the end of the SOAP end point URL of the sender adapter.

    VJ

    (0) 
    1. James Wood Post author
      You’re quite right. However, in some cases, the Web service toolkit used on the client side (e.g. JAX-WS) may not have much flexibility in adjusting the query string parameters of the destination URL. Still, if those parameters can be set, than I agree that that’s the way to go.
      (0) 
  2. Michal Krawczyk
    1. you need to remember to set the delivery semantics
    in case you don’t want to use a dummy queue in the sender adapter but set everything inside the adapter module

    2. 5 years ago (long time) Alessanrdo posted the same thing
    but also showing the content based message routing with it
    The specified item was not found.
    the only thing which got changed is the method for creating the queue

    Regards,
    Michal Krawczyk

    (0) 

Leave a Reply