Skip to Content
Author's profile photo Former Member

SFTP using custom adapter module Part2 – Sender

The second blog on sftp adapter module, which I wanted to publish soon after the first one but couldn’t do it and here I am now. In first blog I wrote about Receiver module which was quite easy as we just have to invoke our receiver channel to deliver the message which will in turn invoke the SFTP receiver module and write file on SFTP server. But in case of Sender scenario where we need to read files from SFTP server, our sender SFTP module won’t work by itself because it cannot poll files and thus for that we will have to use “Trigger file”. The trigger file is nothing but an empty file available on local drive, The sender File adapter will poll this trigger file on test mode at defined polling interval which will invoke SFTP module to read files from remote sftp server at same polling interval.


Now that we have read file from sftp server using module the standard file adapter would still try to send triger file content into message queue, whereas we want the content of file read from sftp server. For this we will have to replace the message content polled by standard file adapter with the content read from SFTP server and put that into messaging queue. The code below shows how that is handled, The remaining module parameters and other necessary functionality like file archiving are also needs to be included in module parameter and in the module code.




/**
*
*/
package com.sap.adaptermodule;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
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.jcraft.jsch.SftpATTRS;
import com.sap.aii.af.lib.mp.module.Module;
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.MessagePropertyKey;
import com.sap.engine.interfaces.messaging.api.XMLPayload;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
/**
* @author ambharti
*
*/
public class SenderSFTPBean implements SessionBean, Module {
    // private Log logger = LogFactory.getLog(getClass());
    private SessionContext myContext;
    public void ejbRemove() {
    }
    public void ejbActivate() {
    }
    public void ejbPassivate() {
    }
    public void setSessionContext(SessionContext context) {
        myContext = context;
    }
    public void ejbCreate() throws CreateException {
    }
    // Start custom function of SFTP
    @SuppressWarnings("unchecked")
    public ModuleData process(ModuleContext mc, ModuleData inputModuleData)
            throws ModuleException {
        Object obj = null;
        Message msg = null;
        MessageKey amk = null;
        InputStream bis = null;
        String lv_del_flag = null;
        try {
            // Retrieves the current principle data, usually the message ,
            // Return type is Object
            obj = inputModuleData.getPrincipalData();
            // A Message is what an application sends or receives when
            // interacting with the Messaging System.
            msg = (Message) obj;
            // MessageKey consists of a message Id string and the
            // MessageDirection
            amk = new MessageKey(msg.getMessageId(), msg.getMessageDirection());
            // Reading file name from message header
            MessagePropertyKey mpk = new MessagePropertyKey("FileName",
                    "http://sap.com/xi/XI/System/File");
            String filename = msg.getMessageProperty(mpk);
            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "Filename is "
                    + filename);
            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                    "Input file read successfully");
            // Archiving target file on FTP server
            {
                String HostName = (String) mc.getContextData("HostName");
                String Port = (String) mc.getContextData("Port");
                String Directory = (String) mc.getContextData("Directory");
                String Filename = (String) mc.getContextData("Filename");
                String Username = (String) mc.getContextData("Username");
                String Password = (String) mc.getContextData("pwd");
                String PrivateKey = (String) mc.getContextData("PrivateKey");
                String HostKey = (String) mc.getContextData("HostKey");
                //Added for Archive
                String Archive = (String) mc.getContextData("ArchivePath");
                //Added for Archive
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                        "Connecting to SFTP location " + HostName);
                int Portno = Integer.parseInt(Port);
                JSch jsch = new JSch();
                Session session = null;
                // Use key authentication if it is set, else use password
                // authentication
                if (PrivateKey != null && PrivateKey != "") {
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                            "Authenticating key to SFTP");
                    if (Password != null && Password != "") {
                        byte[] passphrase = Password.getBytes();
                        jsch.addIdentity(PrivateKey, passphrase);
                    } else {
                        jsch.addIdentity(PrivateKey);
                    }
                    session = jsch.getSession(Username, HostName, Portno);
                } else if (Password != null && Password != "") {
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                            "Authenticating password to SFTP");
                    session = jsch.getSession(Username, HostName, Portno);
                    session.setPassword(Password);
                }
                if (HostKey != null) {
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                            "Authenticating Hostkey of SFTP server");
                    jsch.setKnownHosts(HostKey);
                    session = jsch.getSession(Username, HostName, Portno);
                } else {
                    session.setConfig("StrictHostKeyChecking", "no");
                }
                session.setTimeout(15000);
                // Connecting to SFTP
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                        "Authenticating to SFTP");
                session.connect();
                Channel channel = session.openChannel("sftp");
                channel.connect();
                ChannelSftp sftpChannel = (ChannelSftp) channel;
                sftpChannel.cd(Directory);
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                        "Connection to SFTP location Successful");
         
                // Check if file exists
                Boolean fileExists = false;
                try {
                Vector<ChannelSftp.LsEntry> list = sftpChannel.ls(Filename);
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                        "File listing is Successful");
         
                for (ChannelSftp.LsEntry entry : list) {
                    Filename = entry.getFilename();
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                    "File found is : " + Filename );
                    fileExists = true;
                    continue;
                }
         
                } catch (Exception ex) {
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                    "File listing is Unsuccessful");
                }
         
                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                "File avaialbale :" + fileExists );
         
                if (fileExists == true)
         
                {
                    Vector<ChannelSftp.LsEntry> list = sftpChannel.ls(Filename);
                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                            "File listing is Successful");
         
                    // Read file
                    try {
                        for (ChannelSftp.LsEntry entry : list) {
                            bis = new BufferedInputStream(sftpChannel.get(entry
                                    .getFilename()));
                            Filename = entry.getFilename();
                            continue;
                        }
                        // bis = new
                        // BufferedInputStream(sftpChannel.get(Filename));
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                                "File read sucessfully : " + Directory + "/"
                                        + Filename);
                        // If file is available set message property filename
                        MessagePropertyKey msz = new MessagePropertyKey(
                                "FileName", "http://sap.com/xi/XI/System/File");
                        msg.setMessageProperty(msz, Filename);
                    } catch (Exception e) {
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                                "Module Exception caught:");
                        // Set flag to not perform delete operation
                        lv_del_flag = "X";
                        Audit.addAuditLogEntry(amk, AuditLogStatus.WARNING,
                                "No such file exist");
                    }
                }
                try {
                    XMLPayload xmlpayload = msg.getDocument();
                    String sXML = convert(bis);
                    byte[] docContent = sXML.getBytes();
                    if (docContent != null) {
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                                "Inside DocContent");
                        xmlpayload.setContent(docContent);
                        inputModuleData.setPrincipalData(msg);
                    } else {
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                                "Data not parsed");
                    }
                } catch (Exception e) {
                    ModuleException me = new ModuleException(e);
                    throw me;
                }
                if (fileExists == true) {
             
                    try {
                 
                        if (Archive != null && Archive != "") {
                        // Archive file
                        String pathname = sftpChannel.realpath(Directory) ;
                        pathname = pathname + "/" + Filename;
                        String archname = sftpChannel.realpath(Archive) ;
                        /* Write time stamp to file*/
                        Date date = new Date(); // get the current date
                        SimpleDateFormat dateFormatter = new SimpleDateFormat(
                                "yyyyMMddHHmmssSSS"); // set the format for date
                        String dfmt = dateFormatter.format(date);
                        dfmt = dfmt + "_";
                        archname = archname + "/" + dfmt + Filename;
                        //Filename = archname;
                        sftpChannel.rename(pathname, archname);
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                        "File Archived in " + archname);
                 
                        }
                        else{
                        // delete file from server
                        sftpChannel.rm(Filename);
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                        "File " + Filename + " Deleted from " + Directory);
                        }
                    } catch (Exception e) {
                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                                "Module Exception caught while deleting or archiving the file:" + Filename);
                        ModuleException me = new ModuleException(e);
                        throw me;
                    }
                }
                sftpChannel.exit();
                session.disconnect();
            }
        } catch (Exception e) {
            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,
                    "Module Exception caught:");
            ModuleException me = new ModuleException(e);
            throw me;
        }
        return inputModuleData;
    }
    public String convert(InputStream is) {
        char[] buff = new char[1024];
        Writer stringWriter = new StringWriter();
        try {
            Reader bReader = new BufferedReader(new InputStreamReader(is,
                    "UTF-8"));
            int n;
            while ((n = bReader.read(buff)) != -1) {
                stringWriter.write(buff, 0, n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stringWriter.toString();
    }
}





The module parameter entries would like like –

And the communication channel logs –

References :

SFTP using custom adapter module Part1 – Receiver

http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/c0b39e65-981e-2b10-1c9c-fc3f8e6747fa?overridelayout=t…

JSch – Java Secure Channel – Examples

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Peter Wallner
      Peter Wallner

      Hello Amol Bharti,

      How have you configured the adapter?

      I am using File sender adapter and tried FTP or NFS.

      How do I have to configure the "Source" tab? If I use NFS I set "Source Directory" to "_" and then in monitoring I get the message "Configured source directory '_' does not exist".


      It seems the adapter module is not triggered!


      Thank you

      Peter

      Author's profile photo Peter Wallner
      Peter Wallner

      I had forgotten the trigger file. Now it looks better

      Author's profile photo Amol Bharti
      Amol Bharti

      Hi Peter - Yes, That's the important part 🙂

      Author's profile photo surya ramireddy
      surya ramireddy

      Hi Morning, Where can we write or deploy this JAVA code in SAP PI 7.0?.  Appreciate your response.

      Thanks,

      Surya