Skip to Content

SFTP Adapter Module in SAP PI 7.0

We don’t have SFTP adapter Module in SAP PI 7.0 so if there is any requirement to connect a SFTP server then either we need to purchase an external adapter or we could create a module in JAVA.

I was having a requirement of placing a file over SFTP server so to solve that I wrote a JAVA code for SFTP adapter module.

Hopefully this will help others to create modules for their requirement.

Parameter Configuration in PI receiver Channel:

hahahah.PNG

/**
* @author ashutosh.a.upadhyay
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package com.sftp;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;

import javax.ejb.CreateException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.sap.aii.af.mp.module.Module;
import com.sap.aii.af.mp.module.ModuleContext;
import com.sap.aii.af.mp.module.ModuleData;
import com.sap.aii.af.mp.module.ModuleException;
import com.sap.aii.af.ra.ms.api.Message;
import com.sap.aii.af.ra.ms.api.MessageDirection;
import com.sap.aii.af.ra.ms.api.XMLPayload;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.aii.af.service.auditlog.AuditDirection;
import com.sap.aii.af.service.auditlog.AuditLogStatus;
import com.sap.aii.af.service.auditlog.AuditMessageKey;
/**
* @ejbHome <{com.sap.aii.af.mp.module.ModuleHome}>
* @ejbLocal <{com.sap.aii.af.mp.module.ModuleLocal}>
* @ejbLocalHome <{com.sap.aii.af.mp.module.ModuleLocalHome}>
* @ejbRemote <{com.sap.aii.af.mp.module.ModuleRemote}>
* @stateless
*/
public class SFTPAdapterModule implements SessionBean, Module {
private SessionContext myContext;

AuditMessageKey amk;

public void ejbRemove(){
}
public void ejbActivate(){
}
public void ejbPassivate(){
}
public void setSessionContext(SessionContext context){
  myContext = context;
}
public void ejbCreate() throws CreateException {
}

public ModuleData process(ModuleContext moduleContext,ModuleData inputModuleData)throws ModuleException {
  try {
  Object obj = inputModuleData.getPrincipalData();
  Message msg = (Message) obj;
  String SFTPHOST = (String) moduleContext.getContextData(“SFTPHostorIP”);
  String SFTPPORT = (String) moduleContext.getContextData(“SFTPPort”);
  String SFTPUSER = (String) moduleContext.getContextData(“SFTPUserName”);
  String SFTPPASS = (String) moduleContext.getContextData(“SFTPpassword”);
  String destDir =  (String) moduleContext.getContextData(“TargetLocation”);
  String fileName = (String) moduleContext.getContextData(“SFTPFileName”);
    
    if (msg.getMessageDirection()== MessageDirection.INBOUND)
    amk = new AuditMessageKey(msg.getMessageId(),AuditDirection.INBOUND);
    else
    amk = new AuditMessageKey(msg.getMessageId(),AuditDirection.OUTBOUND);
     
    XMLPayload xp = msg.getDocument();
   
 
  Hashtable mp = (Hashtable) inputModuleData.getSupplementalData(“module-parameters”);
  if (fileName ==””){
   fileName = (String) mp.get (“FileName”);
  }
  if (destDir ==””){
    fileName = (String) mp.get (“Directory”);
  }  
    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”SFTP adapter module called….”);
  
    if (xp != null){
     Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Connecting to SFTP….”);
   byte by[] = convert(xp.getInputStream(),SFTPHOST,SFTPPORT,SFTPUSER,SFTPPASS, fileName, destDir);
     Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”File placed successfully”);
     xp.setContent(by);
    }
  
    inputModuleData.setPrincipalData(msg);
    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Principle data is set successfully.”);
    }
    catch (Exception e){
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Module Exception Caught .”);
  ModuleException me = new ModuleException(e);
  throw me;
    }
    return inputModuleData;
}

public byte [] convert(InputStream inputstream,String host,String port, String username,String password, String fileName, String dir) throws Exception {
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
String file =””;
  try
  {  
  Date date = new Date();
  SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmssSSS”);
  String formattedDate = sdf.format(date);
  fileName = fileName+formattedDate;

  JSch jsch = new JSch();
  int portNo = Integer.parseInt(port);
  session = jsch.getSession(username,host,portNo);
  session.setPassword(password);
  java.util.Properties config = new java.util.Properties();
  config.put(“StrictHostKeyChecking”, “no”);
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Establishing Connection…”);
  session.setConfig(config);
  session.connect();
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Session Established”);
  channel = session.openChannel(“sftp”);
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Connecting the channel..” );
  channel.connect();
  channelSftp = (ChannelSftp) channel;
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Hitting the directory” );
 
  channelSftp.put(inputstream,fileName); 
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”File placed..” );
     
  channelSftp.disconnect();
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Channel Disconnected…” );
    
  session.disconnect();
  sdf = new SimpleDateFormat(“dd/MM/yyyy”);
  formattedDate = sdf.format(date); 
  file = “<FileName> file placed to SFTP server at “+formattedDate;
 
  inputstream.close();
  Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Server Disconnected…” );
}
    catch (Exception e) {
    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,”Exception in Convert Method.”);
    channel.disconnect();
  session.disconnect();
}
return file.getBytes();
}
}

22 Comments
You must be Logged on to comment or reply to a post.
  • Hello, having issues with this module adapter using Receiver File.  I get error in the convert method.

    byte by[] = convert(xp.getInputStream(),SFTPHOST,SFTPPORT,SFTPUSER,SFTPPASS, fileName, destDir);


    here are my paramters

    SFTPHost: IP address

    SFTPPORT: 22

    SFTPUSER: username

    SFTPASS: password

    filename: delivery.xml

    destdir: /norske

    Any ideas why I am experiencing this error?

  • Hello Ashutosh,

    Got the SFTP Module to work now.  But do you experience the behavior that the messages using the SFTP Module are having status = WAIT instead of Successful?

    • If I am not wrong, you are using JDBC adapter and SFTP module configured in it. The wait status is because of the database issue, you must see the error details in the Audit log of the messages in waiting.

  • Here is the error message in the Message Logs: Delivery of the message to the application using connection File_http://sap.com/xi/XI/System failed, due to: com.sap.aii.af.ra.ms.api.DuplicateMessageException: Message ID e46c0191-c998-bdf1-bc4e-0017a477def1(INBOUND) already exists in database: com.sap.sql.DuplicateKeyException: ORA-00001: unique constraint (UNKNOWN.obj#=61379) violated.

    • This seems to be DATABASE Error, in my module I used SFTP module in FTP adapter and placing a log file just.

      The above error is not because of SFTP module, your JDBC channel is posting same data to the database.

    • Hi Bryan,

      Thanks for the Audit log, now I understood the error. The issue is with the duplicate message entry inside of the PI database. You must have tried reprocessing the messages in the wait status. Could you please look out the specific message IDs mentioned in erroneous messages and cancel them or create a new message entry for next messages.

      Ashutosh

  • Hello Ashutosh,

    Cancelled the message and did a re-sent from the source system.  Here are the message logs

    FTP channel4.JPG

    FTP channel5.JPG

    It seems that after successfully placing the file via SFTP in the target system, it will use then try to connect to the FTP system using the standard way; causing the message to be in WAIT

  • Hello,

    works well 🙂

    I found one flaw though:

    In your convert() method the “dir” is never read (which is the “destDir”).

    So I added the following line “channelSftp.cd(dir);”

    to the convert() method.

    Best regards,

    Peter