Skip to Content

Adapter Module: ReplaceString

Adapter Module: ReplaceString


ReplaceString module is used to replace strings within the xml text of the payload of the message. It can be used to modify the message structure before it gets in PI and also before it gets out. It is useful when there are strings like namespaces, types, etc that PI can’t “understand” or that PI is unable to include in outbound messages.

The module obtains a pair of string : <OldString>;<NewString> as parameter. Reads the payload of the message and converts it to a string. Then it searches <OldString> within the message and replace each occurrence with <NewString>. Finally it returns the message modified. If OldString can’t be found in the message nothing is modified and the original message is returned.

The module accepts multiple string pairs to allow multiple replacements in a single execution.


Enterprise Java Bean Project: ReplaceString-ejb

Enterprise Java Bean Application: ReplaceString-ear


The module can be used in any kind of Sender and Receiver adapters.


This section describes all the activities that have to be carried out in order to configure the module.

Entries in processing sequence

Insert the module in front of the adapter module as shown in the picture below.

Entries in the module configuration

The table below shows the possible parameters and values of the adapter module.

Parameter Type Possible values Description Example
separator Optional

Any alphanumeric character.

Default value: ‘|’

This parameter configures the character that separates a pair of strings.

separator = ‘;’


Pair of strings separated by “separator” character.

<OldString><separator>[<NewString>, blankString,emptyString].

Default value: none.

This parameter is used to obtain Old string to be replaced by the New string in the message. The pair is separated by “separator”. As Adapter module tab in PI trims strings by the right side, if it’s needed to replace OldString by a blank string or an empty string, the parameters blankString or emptyString have to be used.




(*) The parameter name can be any string: param1, parameter, aaa, etc.


Payload data before execution:


Module parameters:

separator = ‘;’

param1 = ’RECORDSET;ROW’

param2 = <MT_ROOT>;<MESSAGE type=TYPE>

param3 = </MT_ROOT>;</MESSAGE>

param4 = <DATA>;emptyString

param5 = </DATA>;emptyString

Payload data after execution:



package com.arms.integrations;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import java.util.*;
* @author Roger Allué i Vall
public class ReplaceStringBean implements SessionBean, Module {
    private SessionContext myContext;
    private static final String C_SEPARATOR_STRING = "separator";
    private static final String C_AUX_SEPARATOR = "|";
    private static final String C_MODULEKEY_STRING = "module.key";
    private static final String C_BLANK_STRING = "blankString";
    private static final String C_EMPTY_STRING = "emptyString";
    /* (non-Javadoc)
     * @see javax.ejb.SessionBean#ejbActivate()
    public void ejbActivate() throws EJBException, RemoteException {
        // TODO Auto-generated method stub
    /* (non-Javadoc)
     * @see javax.ejb.SessionBean#ejbPassivate()
    public void ejbPassivate() throws EJBException, RemoteException {
        // TODO Auto-generated method stub
    /* (non-Javadoc)
     * @see javax.ejb.SessionBean#ejbRemove()
    public void ejbRemove() throws EJBException, RemoteException {
        // TODO Auto-generated method stub
    /* (non-Javadoc)
     * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
    public void setSessionContext(SessionContext arg0) throws EJBException,
            RemoteException {
        // TODO Auto-generated method stub
        myContext = arg0;
    /* (non-Javadoc)
     * @see javax.ejb.SessionSynchronization#afterBegin()
    public void afterBegin() throws EJBException, RemoteException {
        // TODO Auto-generated method stub
    /* (non-Javadoc)
     * @see javax.ejb.SessionSynchronization#afterCompletion(boolean)
    public void afterCompletion(boolean arg0) throws EJBException,
            RemoteException {
        // TODO Auto-generated method stub
    /* (non-Javadoc)
     * @see javax.ejb.SessionSynchronization#beforeCompletion()
    public void beforeCompletion() throws EJBException, RemoteException {
        // TODO Auto-generated method stub
    public void ejbCreate() throws javax.ejb.CreateException {
    public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData)    throws ModuleException {
        ByteArrayOutputStream payloadOut = null;
        int inputByte = 0;
        String payloadStr = "";
        Message msg;
        Enumeration paramList;
        String sep, paramKey,param, strArray[];
        try {
             msg = (Message) inputModuleData.getPrincipalData();
             MessageKey amk = new MessageKey(msg.getMessageId(), msg.getMessageDirection());
             Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,".-Module beginning");
payloadStr = new String(msg.getDocument().getContent(),"UTF-8");
            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Payload before execution:" );
            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,payloadStr );
             sep = moduleContext.getContextData(C_SEPARATOR_STRING);
             if ( sep == null ) {
                sep = C_AUX_SEPARATOR;
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Default separator used: " + sep);
             else {
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Separator found: " + sep);
             paramList = moduleContext.getContextDataKeys();
               while( paramList.hasMoreElements()) {
                    paramKey = (String) paramList.nextElement();
                 //Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"ParamKey: " + paramKey);
                 param =  moduleContext.getContextData(paramKey);
                 //Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Param: " + param);
                 if ( ! paramKey.equals(C_SEPARATOR_STRING) && ! paramKey.equals(C_MODULEKEY_STRING) ){
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"ParamKey: " + paramKey);
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Parameter: " + param);
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Separator: " + sep);
                    strArray = param.split(sep);
                    if (strArray != null){
                       if ((! strArray[0].equals(null)) && (! strArray[1].equals(null))){
                        if ( strArray[1].equals(C_BLANK_STRING)){
                            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Blank String");
                            strArray[1]=" ";                   
                        else if (strArray[1].equals(C_EMPTY_STRING)){
                            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Empty String");
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution strArray[0]: " + strArray[0]);
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution strArray[1]: " + strArray[1]);
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution payloadStrA : " + payloadStr);   
                        payloadStr = payloadStr.replaceAll(strArray[0],strArray[1]);
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution payloadStrB : " + payloadStr);
             Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Payload after replacement:" );
             Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,payloadStr );
             payloadOut = new ByteArrayOutputStream();
        catch(Exception e) {
            ModuleException me = new ModuleException(e);
            throw me;
        return inputModuleData;

You must be Logged on to comment or reply to a post.
  • Hello Aaron,

    It seems something’s wrong with your ear.  Could you please tell me how are you deploying you ear?  You can check if the module is correctly deployed from the perspective Deployment of NWDS. On left panel you should see that the module is running (in green).

    Regards !

    • Hi, I think the Ear is deployed OK now. However in RWB com channel monitor I get error: “Message processing failed. Cause: java.lang.ArrayIndexOutOfBoundsException: 1″

      Does this perhaps mean my module parameters are maybe wrong? I tried with single quotes around the replace strings also. Is there a way to set breakpoint in NWDS or simulate the execution at runtime?


      12.02.2015 17:31:35.788 Information MP: entering1
      12.02.2015 17:31:35.790 Information .-Module beginning
      12.02.2015 17:31:35.790 Information MP: processing local module localejbs/ReplaceString
      12.02.2015 17:31:36.017 Information <ns0:MyMessage> … [contents omitted] … </ns0:MyMessage>
      12.02.2015 17:31:36.017 Information ParamKey: param1
      12.02.2015 17:31:36.017 Information Parameter: ns0;foobar
      12.02.2015 17:31:36.017 Information Payload before execution:
      12.02.2015 17:31:36.017 Information Separator found: ;
      12.02.2015 17:31:36.017 Information Separator: ;
      12.02.2015 17:31:36.018 Error MP: exception caught with cause java.lang.ArrayIndexOutOfBoundsException: 1
      12.02.2015 17:31:36.019 Error Adapter Framework caught exception: 1
      12.02.2015 17:31:36.020 Error Delivering the message to the application using connection File_ failed, due to: java.lang.ArrayIndexOutOfBoundsException: 1.
      12.02.2015 17:31:36.025 Information The asynchronous message was successfully scheduled to be delivered at Thu Feb 12 17:36:36 CET 2015.
      12.02.2015 17:31:36.025 Information The message status was set to WAIT.
      • Think I found the issue here is with the separator. If I use ‘;’ in the config I get ArrayIndexOutOfBounds, but if I do not quote it in config it sends the message through the module OK.

      • I had only one other issue but solved it myself.

        On lines 137, 138 Java replaceAll was not making the substitution until I converted the String Arrays to regular Strings using .toString() method. After that with the same parameters it started to work. This could maybe be down to our old java version? I saw from your document you use the latest and greatest.

        Thanks so much Roger for posting this document and giving me some hints!!! I now have a basic understanding of how to write and deploy adapter modules.

  • Hi Roger

    I am doing a REST — PI — ECC synchronous scenario. The xml payload is converted to JSON by REST channel and this causes an unwanted backward slash to be added to the payload.

    like this




    is there any module that can remove the backward slash from the target payload



    • Hello Midhun,

      Sorry, but I didn’t use the REST Adapter yet. However, If the URL is added to the payload you can always use my module.

      Just to understand a bit more the problem, could you please paste an example of your payload?


      • Hi Roger

        This is the payload:


           “MT_EmployeeNumber_CRN_Response_Receiver”: {

             “EmployeeNumberTable”: [


                 “EmployeeNumber”: “134541”,

                 “EmployeeName”: Mark,

                 “EmployeeDescription”: “TEST 123”,

                 “EmployeeGroup”: “SAP”,

                 “links”: {

                   “self”: {









        This payload is converted from xml to JSON. When the conversion is done an additional backward slash is added in front of all the forward slashes in the url.

        This is a synchronous scenarios, REST adapter at sender side and SOAP adapter at receiver side.

        My requirement is to take the backward slash from the JSON Payload


        • Hello Midhun,

          My module ReplaceString treats the payload as text, so it shouldn’t distinguish between xml and json messages. Notice that the module uses the java method replaceAll. This method expects a regular expression and you should escape backslashes.

          Could you configure the module with the following parameters?




          • Look, I have created a simple class to test replaceAll method:

            import java.util.Scanner;

            public class Test {



                public static void main(String[] args) {



                    Scanner keyboard = new Scanner(;


                    System.out.println(“Enter String:”);

                    String str = keyboard.nextLine();

                    System.out.println(“Enter Str1:”);

                    String str1 = keyboard.nextLine();

                    System.out.println(“Enter Str2:”);

                    String str2 = keyboard.nextLine();


                    String str3 = str.replaceAll(str1, str2);


                    System.out.println(“Str: ” + str);

                    System.out.println(“Str1: ” + str1);

                    System.out.println(“Str2: ” + str2);

                    System.out.println(“Str3: ” + str3);




            And this is the result with your original string and the parameters I mentioned above:

            Enter String:


            Enter Str1:


            Enter Str2:


            Str: http:\/\/host:port\/RESTAdapter\/xyz

            Str1: \\/

            Str2: /

            Str3: http://host:port/RESTAdapter/xyz


          • Thanks a lot for your time, Roger

            I am working on it and will update you. Your help was priceless and really appreciate the time you have taken to help me

          • Hello Roger,

            Did you test your module with the REST adapter, Can you please share your experience.

            Even I am facing issues handling backslash in xml to JSON conversion.

            So would like to hear from you.



  • Hi Roger,

    Thank you for sharing your module. I think this will be helpful in many scenarios.

    However, I have some doubts about following piece of code:

       while((inputByte = != –1) { 

               payloadStr = payloadStr + (char) inputByte; 


    As provides a byte, and you change it to (char), this leads to errors for all multi-byte UTF-8 character. For example the German character ‘ä’ (hex c3 a4) would be transformed to ‘ä’

    I recommend using following code line:

         payloadStr = new String(msg.getDocument().getContent(),”UTF-8″);

    This is the proper way to tranform a byte array into a String.



  • Hello Apu,

    there are plenty of blogs on how to create your own module. Don’t get me wrong, but there’s a difference between sharing knowledge and working for free.

    Good luck.

  • Hi,

    I have a problem with conversion on REST Receiver adapter, method GET. The communication channel is not converting the json payload to html, so the payload that returns to S4Hana is empty.

    The interface is sycronous: SAP S4Hana (Proxy) -> SAP PO (REST) -> External System (GET method).

    Here is the json returned from external system.

    {“Details”:{“OrderDetails”:[{“OrderID”:”0″,”OrderNo”:”00010″ }],”CustomerID”:”00001″,”UserID”:””,”Name”:””,”PCode”:””,”Status”:”Sucess”,”Message”:”Record Inserted Successfully”}}

    Here is the error message from PO system.

    MP: exception caught with cause Invalid JSON message content used; Message: “JSONArray text must end with ] at character 28 of 

    Bellow are the images.



    Error Message

    Please suggest me to resolve this error.





  • Hello everybody

    I’m trying to implement the Adapter Module ReplaceString for PI 7.4. However

    the class cannot be imported as it does not

    exists anymore. I didn’t find the JAR-File anymore on the OS of the PI.

    How to proceed in order to be able to use the Audit class?

    Thanks for your feedback.

    Kind regards



    • Hello Chris,


      The audit statements are just to trace the module execution and see what is doing in the channel monitoring log. If you want you can ommit them.


  • Hello Roger

    thanks for your feedback.

    I’ve found now a way to access the audit classes:
    the classes and are used
    to define the audit variable. So I didn’t have to comment the audit statements (because
    they are still important for the trace messages to me).

    I’ve deployed then the ReplaceString EAR according to the following link:

    After the deployment I can see 4 objects in the JNDI browser (like in )

    Unfortunately the adapter module ReplaceString does not seem to get called
    (I’ve inserted ReplaceString before the CallSapAdapter, like shown in this blog).

    In the message protocoll I see only:
    “MP: processeing local module localejbs/CallSapAdapter” but I cannot find
    “messages like “.-Module beginning” .

    Somehow it seems that the module is not being called even though I’ve could successully
    deploy it and it can be seen in the JNDI-Browser.

    Do you have any clue how I can remedy to this problem?

    Thanks for your feedback.

    Kind regards

  • PS2: I’ve found a difference in the EJB explorer between ReplaceStringBean and PlainConverterModule: the status is different for “

    => could this be the reason that ReplaceString module is not being called? How to remedy?


  • PS3: when I execute the test function in the EJB explorer I get the following error message for ReplaceString:


    Caused by: javax.ejb.EJBTransactionRolledbackException: ASJ.ejb.005044 (Failed in component:

    Exception raised from invocation of public,

    throws method on bean instance

    for bean*annotation|ReplaceStr_EJB.jar*xml|ReplaceStringBean in application; nested exception is: java.lang.NullPointerException: while trying to invoke

    the method of a null object loaded from

    local variable ‘inputModuleData’; nested exception is: javax.ejb.EJBException: ASJ.ejb.005044

    (Failed in component: Exception raised from invocation

    of public, throws method on bean

    instance for bean*annotation|ReplaceStr_EJB.jar*xml|

    ReplaceStringBean in application; nested exception is: java.lang.NullPointerException:

    while trying to invoke the method of a null

    object loaded from local variable ‘inputModuleData’



    However the inputModuleData variable is instanciated like in your code above:


    public ModuleData process(ModuleContext moduleContext,
    ModuleData inputModuleData) throws ModuleException {

    Message message = (Message) inputModuleData.getPrincipalData();
    MessageKey messageKey = message.getMessageKey();



    Any clue on how to remedy on that?



    Hello Roger

    the problem is solved: everythin was correct with the EJB Explorer.
    I didn’t properly call the ReplaceString Module in the sender adapter, thats
    why it didn’t get called. Now it’s working.

    However I have a question regarding your statement above:

    while((inputByte = != –1) {
    payloadStr = payloadStr + (char) inputByte;

    You replaced it by

    payloadStr = new String(msg.getDocument().getContent(),”UTF-8″);

    However this statement uses the SAXParser and it throws an expection when e.g.
    I want to get rid of a @ (by replacing @ by emptystring) in REST response message
    where the JSON-Structure is converted to an XML structure.
    So in this case it would be better to have your piece of code (no SAXParser involved)
    than the suggested statement by Stefan Grube (knowing that in this particular case
    the problem with the Umlaute ä can arise).

    Could you just share how in your example with

    while((inputByte = != –1) {
    payloadStr = payloadStr + (char) inputByte;

    you did define and initialize payloadIn (with class Inputstream or other)?

    Thanks for your feedback.

    Kind regards