Overview
In a business scenario, a group of users send attachments to one mail-id. They can send multiple attachments per mail. So, here, we need to find out a way to extract all attachments with their original names from a mail and store it in some folder.
Using Sender-Mail adapter, we read mails with attachments.
For storing attachments to specific sap application directory, we use Receiver-File Adapter along with a custom java adapter module.
Note: Receiver-File-Adapter can store only 1st attachment, so, we create a custom adapter module for this channel which will store multiple attachments to folder.
Sender/Receiver Communication channels can be referred from below link:
Pre-requisites:
Pre-requisites to create a custom java adapter module form SAP PI 7.11 is as below:
- SAP NetWeaver Developer Studio 7.1
- Java Runtime Environment 1.6 (Jre 1.6)
- SAP library (or jar) files for required for module development
- sap.aii.af.lib.mod.jar : <bin>/ext/com.sap.aii.af.lib/lib
- com~tc~logging~java~impl.jar : <bin>/system
- sap.aii.af.svc_api.jar : <bin>/services/com.sap.aii.af.svc/lib
- sap.aii.af.cpa.svc_api.jar : <bin>/services/com.sap.aii.af.cpa.svc/lib
- sap.aii.af.ms.ifc_api.ja r : <bin>/interfaces/com.sap.aii.af.ms.ifc/lib

- Include above jar files in the library classpath of SAP Netweaver Developer Studio 7.1 via below steps:
- Navigate to Windows → Preference → expand “Java” → select "Build Path" → select “Classpath Variables” → Click “New” to create a "New Variable Entry" → input "Name" as "PI_AF_LIBS" → select "Path" (above jar location)
- NwceTool
- This will help to convert EAR files to SDA files
- It uses JRE 1.6
Java Adapter Module Code:
- Below java adapter module code is been written to get SAP-Directory path with external module input variable 'SapDirPath' and save the atatchments with original fileName into the path:
/**
*
*/
package com.sap.adaptermodule;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
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.service.auditlog.Audit;
import com.sap.engine.interfaces.messaging.api.Message;
import com.sap.engine.interfaces.messaging.api.MessageKey;
import com.sap.engine.interfaces.messaging.api.Payload;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Iterator;
/**
* @author User
*
*/
public class MAttachToDirBean implements SessionBean, TimedObject {
/* (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
}
/* (non-Javadoc)
* @see javax.ejb.TimedObject#ejbTimeout(javax.ejb.Timer)
*/
public void ejbTimeout(Timer arg0) {
// TODO Auto-generated method stub
}
public void ejbCreate() throws javax.ejb.CreateException {
}
private SessionContext myContext;
MessageKey amk = null;
public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData) throws ModuleException
{
Object obj = null;
Message msg = null;
String SapDirPath = null;
try
{
obj = inputModuleData.getPrincipalData();
msg = (Message) obj;
amk = new MessageKey(msg.getMessageId(),msg.getMessageDirection());
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "JAM-MAttachToDir| Custom-Java-Adapter-Module (localejbs/MAttachToDir) to store mutliple attachments to directory");
//Get user-input as a "module.key" parameters from communication channels
//Input-1: 'SapDirPath' to get folder path where attachments will be stored
SapDirPath = (String) moduleContext.getContextData("SapDirPath");
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "JAM-MAttachToDir| Directory Path input (SapDirPath)= " + SapDirPath);
//Get the input attachment from the source message)
Iterator itr = msg.getAttachmentIterator();
while(itr.hasNext()){
//handle attachment
Payload payload = (Payload) itr.next();
//get attachment name
String atchnm = payload.getContentType(); //this gives output like "application/octet-stream;name=""fnam1.csv"
atchnm = atchnm.replaceAll("\"", ""); //replace all quoteString (i.e. ") with blank
int i1 = atchnm.lastIndexOf("=") + 1;
String atchmntNm = atchnm.substring(i1,atchnm.length());
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "JAM-MAttachToDir| Attachment found as " + atchmntNm);
//Write file to directory
byte [] inpbyt = payload.getContent();
File path = new File(SapDirPath + "/" + atchmntNm);
FileOutputStream fos = new FileOutputStream(path);
fos.write(inpbyt);
fos.flush();
fos.close();
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "JAM-MAttachToDir| " + atchmntNm + " copied to folder " + SapDirPath);
}
}catch (Exception e) {
ModuleException me = new ModuleException(e);
throw me;
}
return inputModuleData;
}
}
Steps to Create Java Adapter Module:
- Create an EJB project in "SAP NetWeaver Developer Studio 7.1"
- Assign project names to the EJB and EAR projects
- EJB Project Name: MAttachToDir_EJB.
- EAR Project Name: MAttachToDir_EAR (check the option to add EAR project).
- Click "Next".

- Choose the correct EJB version.
- Configure Module Project as → SAP EJB J2EE 1.4 Project.
- Choose the EJB Module → 2.1.
- Click "Next".

- Uncheck the flag to create the EJB client jar interfaces.

- Click "Finish"
- Please note, 2 projects will be created, an EJB project (MAttachToDir_EJB) and an EAR project (MAttachToDir_EAR).
- Create an Enterprise Bean in the EJB project
- Right-click on the "MAttachToDir_EJB".
- Select: New → EnterpriseBean.

- Create the package and class for the EJB project
- EJB Name: MAttachToDir
- Bean Type: Select the dropdown “Stateless Session Bean”
- Default EJBPackage: com.sap.adaptermodule
- "generate default interfaces" => "Uncheck" in checkbox
- "add optional interfaces" => "Check" in checkbox
- Click "Next".

- Assign user-module interfaces | Component and Local Interfaces parameters:
- Bean class: keep same value which appears default
- Remote interface: com.sap.aii.af.lib.mp.module.ModuleRemote
- Home interface: com.sap.aii.af.lib.mp.module.ModuleHome
- Local interface: com.sap.aii.af.lib.mp.module.ModuleLocal
- LocalHome interface: com.sap.aii.af.lib.mp.module.ModuleLocalHome
- "Service End point": => "Uncheck" in checkbox
- Click ‘Finish’

- Examine and verify the content of ejb-jar.xml
- On the left panel, navigate: EJB project → ejbModule → META-INF.
- Double click on the "ejb-jar.xml".

- When the “ejb-jar.xml” is displayed on the right panel, select the "Enterprise Beans" tab at the bottom.
- Expand "Session Beans" and select "MAttachToDir".
- All the local and remote interfaces should be displayed.

- The “Service endpoint” should be empty. If not, then go to “Source” and edit the tag “<service-endpoint>”with blank value

- Enter the JNDI name in the ejb-j2ee-engine.xml
- On the left panel, double click on the "ejb-j2ee-engine.xml".

- "Ejb-j2ee-engine.xml" will be displayed on the right panel
- Expand “Session beans” and click on “MAttachToDir”
- Enter the "JNDI Name" for e.g. "MAttachToDir"
- Save the file.

- Include external libraries in the EJB project so the java class can be compiled
- Right click on the EJB project.
- Navigate to "Build Path".
- Select "Configure Build Path".

- In the Properties dialogue box, click the "Add Variable".

- Select the variable, "PI_AF_LIBS", created earlier

- Click on "Extend".


- Enter the code for “MAttachToDirBean”
- Copy and paste code from above to below project file


- Delete the package containing the Local and Remote interfaces from the build
- Expand the “build” folder in the EJB project.
- Delete all the folders created under build → classes → com → sap -> aii
- Do not delete " build → classes → com → sap -> adaptermodule"

- Configure the EAR project: The EAR file contains the following:
- JAR file created from the EJB project.
- It has configuration information of the libraries, services and interfaces that will be used by the user-module in the EJB.
- It contains the SAP manifest file, which has unique identifiers for each specific EAR. The manifest information is generated uniquely each time it is modified.
- Steps to Configure EAR:
- Exporting SAP EAR File
- Right Click on EAR project -> Export -> SAP EAR File


- Custom java adapter module has been created as EAR file "MAttachToDir_EAR.ear "
Steps to Covert EAR files to SDA Files using NWCE-Tool:
- From above steps, java adapter module EAR file "MAttachToDir_SDA.ear" gets created.
- To use this module in SAP-PI, we need to convert it in to SDA file format with ".sda" extension.
- Pr-requisites for EAR to SDA file conversion:
- Java Jre1.6 Check Java Jre1.6 Directory (here C:\Program Files\Java\jre1.6.0_01)
- nwcetool Copy nwcetool folder in to C:\NWDS
- Any local Windows system
- Command line steps for EAR to SDA file conversion:
- cmd>cd \
- cd C:\NWDS\NWCE_TOOLS\tools\nwcetool
- SET JAVA_HOME=C:\Program Files (x86)\Java\jre6
- SET NWCETOOLLIB=C:\NWDS\NWCE_TOOLS\tools\lib
- nwcetool.bat

- createsda -n MAttachToDir -v sap.com -l MAttachToDir -c 2 -type J2EE C:\Users\User\Desktop\bLOG_jAM\MAttachToDir_EAR.ear C:\Users\User\Desktop\bLOG_jAM\MAttachToDir_SDA
- Where
- createsda -n <JNDI-Name> -v Vendor-Name -l <JNDI-Name> -c 2 -type J2EE <source EAR file path> <destination SDA file path>

- Now rename file “MAttachToDir_SDA.ear” to “MAttachToDir_SDA.sda”

Steps to Deploy SDA files in PI-Server:
- SDA File deployment using Telnet in SAP-PI:
- Place the sda file (MAttachToDir_SDA.sda) in directory '/usr/sap/trans/EPS/in/'
- Update the file '/usr/sap/trans/EPS/in/deploylist.txt' with the file to be deployed
- Use below commands
- telnet localhost <port>
- Username: <enter j2ee_admin user>
- Passwrod: <*******>
- deploy list=/usr/sap/trans/EPS/in/deploylist.txt version_rule=all
- Post Deployment, SDA file gets extracted in below SAP-PI's folder path, having folder name as of JNDI-Name 'MAttachToDir'
- /usr/sap/<systemID>/<instance>/j2ee/cluster/apps/sap.com/MAttachToDir/
Steps to check deployed custom Java-Adapter-Module in SAP-PI/PO server:
- In SAP-PI, go to NWA link [ http://<sap-pi-host>:<sap-pi-port>/nwa ] and follow below steps:
- In NWA -> Problem Management -> Java -> JNDI Browser
- In NWA -> Operation Management -> System -> Start & Stop -> Java EE Applications
- In SAP-PO, go to NWA link [ http://<sap-pi-host>:<sap-pi-port>/nwa ] and follow below steps:
- In NWA -> search 'JNDI'
- or in NWA -> Troubleshooting -> Java -> JNDI Browser -> scroll down to search 'MAttachToDir'
- or in NWA -> Troubleshooting -> Java -> System Information -> TAB 'Component Info' -> 2nd half TableGrid -> Search for Name 'JNDI Name of Module'
- In NWA -> Operation -> System -> Start & Stop -> Java EE Applications -> search 'MAttachToDir'
Thanks for reading...........hope this helps