Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
Showing results for 
Search instead for 
Did you mean: 
Active Contributor
Update 2 Oct 2014: Added section regarding usage of Audit Log


While custom adapter module development is becoming more common, there is still no functionality built into the NWDS/Eclipse IDE to perform basic testing of the module logic. As described by threads like this, it is a pain to redeploy the module into the server each time there are code changes. The adapter module can only be tested in an end-to-end scenario. Even for Proof-Of-Concept developments, a full integration scenario needs to be configured in order to test the module.

This blog attempts to help to reduce the pain in adapter module development by providing an approach to easily perform basic/unit testing prior to server deployment.

This is achieved by introducing a testing class with a static Main method as a wrap-around of the module class. This testing class can then be executed in the IDE directly.


Please be aware that there are limitations to this approach as it is meant for basic/unit testing only. Certain scenario examples in the non exhaustive list below still require end-to-end testing.

- scenarios with dependencies on output of prior module in the module chain

- scenarios with dependencies on actual payload generated by sender adapter

- scenarios that requires connectivity to certain resources (HTTP, FTP, etc) that are not available from the local PC

- scenarios with attachments

Source code

The full source code can be found in the following public repository on GitHub.

GitHub repository for equalize-xpi-tester

Details and Usage

Below are the details of this approach and also an explanation on the different sections, and how those could be changed so that standalone testing can be performed in NWDS.

Testing class with Main method

Create a new testing class with a main method. Ideally put this in a separate package, so that this can be excluded when generating the files for deployment. Copy the source code provided above into the new class - take note of any package renaming as necessary.

Local implementation classes

Several interfaces do not have corresponding implementation classes in the PI JAR library files. In order to be able to compile the test class, the following classes shown below are local classes implementing those interfaces. These only provide basic implementation for testing and are not the same as the full implementation classes in the Adapter Engine.

Module class and message details

Below shows the portion of the code where the module bean is instantiated. This should be changed according to the name of the module bean being developed.

The message details (sender/receiver details, protocol, etc) can also be changed accordingly.

Input file

Location of input file in the local machine running NWDS should be changed accordingly.

Dynamic configuration

Optionally, dynamic configuration can be simulated by adding the entries in the test class using static method addDynCfg(namespace, attribute, value).

Module parameters

Optionally, module parameters can be entered to simulate entries in the module chain by using method put(parameterName, parameterValue).

Module processing and output file

Actual processing logic of the module is executed by the call to the process method of the bean.

Location of output file in the local machine running NWDS should be changed accordingly.

Example Module

Below is a simple example of a custom module (the full code is found in the GitHub repository above) to demonstrate unit testing in NWDS.

The module changes the name of the root element and also adds a prefix to the dynamic configuration filename if module parameter PARAM1 is configured.


public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData) throws ModuleException {
  try {
   // Get input stream
   Message msg = (Message) inputModuleData.getPrincipalData();
   XMLPayload payload = msg.getDocument();
   InputStream inStr = payload.getInputStream();
   // Get the text content
   BufferedReader br = new BufferedReader(new InputStreamReader(inStr));
    ArrayList<String> contents = new ArrayList<String>();
   String lineContent;
   while ((lineContent = br.readLine()) != null) {
   // Modify the root element name
   StringBuilder sb = new StringBuilder();
   for( String line: contents ) {
    if ( line.contains("MT_Calculator_Input")) {
     line = line.replace("MT_Calculator_Input", "New_Root");
    } else {
    // Set changed content
   // If PARAM1 is configured in the module parameters, add that as a prefix to the file name
   String param1 = moduleContext.getContextData("PARAM1");
   if (param1 != null) {
    // Get Dynamic Configuration
    MessagePropertyKey fileNameKey = new MessagePropertyKey("FileName", "");
    String fileName = msg.getMessageProperty(fileNameKey);
    // Set new value Dynamic Configuration
    msg.setMessageProperty(fileNameKey, param1 + "_" + fileName );
   // Update the message
  } catch (Exception e) {
   throw new ModuleException(e.getClass() + ": " + e.getMessage());
  return inputModuleData;

Input and results

Input FileOutput File

Dynamic configuration values displayed in Console output

Audit Log Usage

Audit log is an important logging functionality to provide accurate status of the processing of module. However, audit log is not available during standalone testing in NWDS. Execution of method getPublicAPIAccess of PublicAPIAccessFactory will raise a MessagingException. In order to workaround this, the exception can be caught in a try-catch block, and adding to the audit log is only performed if the audit log object is instantiated. Optionally, for testing in NWDS, the message can be sent to the console output.

Below is the snippet of the logic to handle audit log instantiation and message entry.

   // Get audit log
   MessageKey key = new MessageKey(msg.getMessageId(), msg.getMessageDirection());
   try {
    audit = PublicAPIAccessFactory.getPublicAPIAccess().getAuditAccess();
   } catch (MessagingException e) {
    System.out.println("WARNING: Audit log not available in standalone testing");
   addLog(key, AuditLogStatus.SUCCESS, "CustomFunctionBean: Module Called");

Logic for private method addLog.

private void addLog (MessageKey msgKey, AuditLogStatus status, String message) {
  if (audit != null) {
   audit.addAuditLogEntry(msgKey, status, message);
  } else {
   System.out.println( "Audit Log: " + message);

Additional Reference

Official step-by-step guides by SAP on how to create custom modules

How to Create Modules for the J2EE Adapter Engine (NW2004)

How to Create Modules for the J2EE Adapter Engine (NW7.0)

How to Create Modules for the JEE Adapter Engine 7.1

Developing User Enhancement Modules in the Adapter Engine

Location of JAR library files for Module development

Where to get the libraries for XI development - Process Integration - SCN Wiki

For NWDS 7.3, JAR files are automatically provided by NWDS, so just need to include the XPI Library as shown in the thread below

Issue in Excel to XML Conversion

Links for downloading different versions of NWDS

NWDS Download Links - Java Development - SCN Wiki

Labels in this area