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!
cancel
Showing results for 
Search instead for 
Did you mean: 
sugata_bagchi2
Active Contributor

Sending Notification with attachment using Java Mail API in SAP PI Map

Applies to:  

SAP Process Integration 7.0 and Above Versions. Sending Mail Notification based on Custom errors, Sending error notification with payload as attachment. Control Message Processing in PI based on error.

Summary:

  In many business scenarios we like to enforce the error handling of messages in such a way so that the error can be traced easily and corrective actions can be taken properly.
In SAP PI we have some standard mechanism to handle and report error; these are done by configuring the ALERT in ABAP engine and sending the mail notification of that error to the desired recipients.

But using standard ALERT mechanism we can not create notifications for a   particular kind of error / custom error.
This Article will provide the detail description to use Java Mail API using SAP Process Integration and create such notifications for users.

Author:  Sugata Bagchi Majumder

Company:      IBM Global Business Services, India.

Created on:    27 October 2012

Author Bio:

Sugata B Majumder is a SAP Technical Consultant in IBM Global Business Services. He is working with IBM since 2007 and presently involves with multiple SAP implementation projects for Soulutioning and Designing. His technical expertise includes SAP Process Integration, e-SOA and JAVA/J2EE. He has experience of working in diverse SAP Landscapes and with different integrations, such as SRM, CRM an MDM along with various JMS, Third party systems and B2B Integrations.

Table of Contents

     Introduction ………………………………………………………3

     What is Java Mail API? ..................................................................3       

     Assumption……………………………………………………….4

     Prerequisite ……………………………………………………….4

     Scenario Description and Flow……………………………………4

     Step by Step Solution ……………………………………………..5

     Testing the Scenario ………………………………………………12

     Restriction………………………………………………………….13

    

Introduction:

In many business scenarios we like to enforce the error handling of messages in such a way so that the error can be traced easily and corrective actions can be taken properly.
In SAP PI we have some standard mechanism to handle and report error; these are done by configuring the ALERT in ABAP engine and sending the mail notification of that error to the desired recipients.

But using standard ALERT mechanism we can not create notifications for a   particular kind of error / custom error.
In case of Look up error  inside a mapping or  value mismatch exception for a particular source field we can not generalize it as a mapping error only we need to drill down a bit more. So to report error in this kind of scenario we can use Java Mail API to send mail even with attachment (we can set the source erroneous payload as attachment).

What is Java Mail API ?

The Java Mail API provides a platform-independent and protocol-independent framework to build mail and messaging applications. The Java Mail API is available as an optional package for use with Java SE platform and is also included in the Java EE platform. The Java Mail API allows the developers to add mailing functionalities to their java applications. The Java Mail API provides a platform-independent framework to develop mail and messaging applications in Java technology. Java Mail API is also protocol-independent making it more useful. Java Mail API is designed to provide functionality such as read, compose and send from within a java programs. Current version of Java Mail API can be downloaded from the link given below:-

http://www.oracle.com/technetwork/java/javamail/index-138643.html

Possible Uses of Java Mail API are-

  1. Send Email from any type of java application.
  2. Composing, reading and sending electronic mail.
  3. Send Email from java stored procedure.
  4. Create a GUI Email client.
  5. Dealing with sending and receiving attachments with Email.
  6. To search for messages.

Assumption:

    It is assumed that the NWDS 7.0 or above version is installed in the system where the code has to be developed. Access to ESR (Repository) and ESB (Directory) of a PI system is already in place. A local FTP client/server software (in this case Cerberus is used) is installed.

Prerequisite:

   Knowledge of Basic PI Mapping, Java Mapping and Adapter configuration is required.

Scenario Description and Flow:

According the Business requirement, Client will place a file of Employee details in a source FTP Location and PI will pick up the file. After required transformation thru PI map SAP PI will place the file to another FTP location.

As per the requirement, in PI Mapping a look up needs to be carried out for a source field Employee Department. If look up fails then an alert with that wrong payload should be sent to the client’s mail ID and message processing should not be continued.

Step by Step Solution:

We have to create alert and send notification only incase if look up fails inside PI mapping.
As per the requirement we also have to send the wrong source payload as attachment.

The Java mail API is used here to achieve this requirement.

It is assumed that all the necessary data type and message types and other repository objects are created and the configuration objects are also created for this interface.

Our approach would be to track the error in the mapping level and send mail from PI using Java Mapping.

Step1:    Get the Source payload and create the same inside PI application server using Java Mapping.

Step2:   Determine the   Receiver based on the logic (look up success or not) using graphical mapping.

Step3:       if receiver is determined in step2 correctly populate the receiver list structure (as defined in the Receivers of http://sap.com/xi/XI/System) else create mail with attachment of the file created in the step1 and send to the respective mail IDs and stop processing the message.

The execution of this scenario involves with two Operation Mappings.

  1. Operation Mapping used in Interface Determination on successful receiver determination (look up success).
  2. Operation Mapping used Receiver Determination to determine the correct receiver as a part of Extended Receiver Determination. At this step we also stop processing of message if look up error occurred and receiver not determined. As Extended Receiver Determination is used here, so the Service Interface ReceiverDetermination and its inner objects are used in this Operation Mapping and Message Mapping.

The below Operation Mapping is used for the Extended Receiver Determination, here in the first step mapping the  Java Mapping is used to create the payload. After this a graphical mapping is used to determine the receiver and again a java mapping is used to send notification along with the payload attachment file created in the first mapping.

Step1:   The below Java code is used to create the payload in the PI application server-

                    //Author: Sugata B Majumder

//Build ID: SAP NetWeaver Developer Studio SAP NetWeaver 7.1 Composition Environment SP05 PAT0000

Build id: 200802231406

package com.sap.CreatePayload;

import java.io.BufferedWriter;

import java.io.DataInputStream;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Map;

import java.util.Map;

import com.sap.aii.mapping.api.MappingTrace;

import com.sap.aii.mapping.api.StreamTransformation;

import com.sap.aii.mapping.api.StreamTransformationConstants;

import com.sap.aii.mapping.api.StreamTransformationException;

public class CreatePayload implements StreamTransformation

{

            private MappingTrace trace;

            public void setParameter(Map param)

             {

    if (param != null)

      {

        Object o = param.get(StreamTransformationConstants.MAPPING_TRACE);

        if (o != null && o instanceof MappingTrace)

         {

        trace = (MappingTrace) o;

           }

        }

      }

public void execute(InputStream in, OutputStream out)throws StreamTransformationException

             {

try

                          {

                                    InputStream stdin = new DataInputStream(in);

                                    stdin.reset();

                                    byte[] buffer = getBytesFromStream(stdin);

                                    String str = new String(buffer);

                                    File file = new File("/usr/sap/PIX/put/Payload_Error.txt");

                                    // if file does not exists, then create it

                                    if (!file.exists())

                                    {

                                    file.createNewFile();

                                    }

                                    FileWriter fw = new FileWriter(file.getAbsoluteFile());

                                    BufferedWriter bw = new BufferedWriter(fw);

                                    bw.write(str);

                                    bw.close();

                                    out.write(str.getBytes());

                                    out.close();

                          }

catch(IOException ie)

{

ie.printStackTrace();

}

             }

public int getLengthFromStream(InputStream is ) throws

IOException{

int i = 0;

int length = 0;

try{

while ((i = is.read())> 0){

length ++;

}

}catch (ArrayIndexOutOfBoundsException e) {

  1. e.printStackTrace();

}

return length;

}

public byte[] getBytesFromStream(InputStream is) throws

IOException {

byte[] bytes = new byte[getLengthFromStream(is)];

  1. is.reset();

int offset = 0;

int tmp = 0;

while (offset < bytes.length

&& (is.read(bytes, offset, offset +

(tmp = is.available()))) > 0) {

offset += tmp;

}

if (offset < bytes.length) {

throw new IOException("Could not completely read Inputstream");

}

  1. is.close();

return bytes;

}

}

Step2 In step2 of the operation mapping the graphical mapping is used to determine the receiver based on the logic if look up failed or not. It is assumed that the correct receiver is BC_FTP for example.

                                          

Step3: Here in this step the output of the 2nd mapping is checked inside this  Java Mapping and based on the condition (if Service is BC_FTP or not) the notification is triggered with the attachment. The below Java code is used to create mail notification with attachment-

//Author: Sugata B Majumder

//Build ID: SAP NetWeaver Developer Studio SAP NetWeaver 7.1 Composition Environment SP05 PAT0000 Build id: 200802231406

//Java Mapping to Send mail to Customer incase of specific error for e.g- LookUp error.The mail will also contain the pay-load as attachment.

//Compiled on JDK 1.5 anr JRE 5.0 version

package com.sap.SendMailWithAttachment;

import java.io.BufferedWriter;

import java.io.DataInputStream;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.FileInputStream;

import java.io.OutputStream;

import java.util.Map;

import javax.activation.*;

import javax.mail.internet.*;

import javax.mail.*;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Result;

import javax.xml.transform.Source;

import javax.xml.transform.Transformer;

import javax.xml.transform.TransformerFactory;

import javax.xml.transform.dom.DOMSource;

import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.w3c.dom.Element;

import com.sap.aii.mapping.api.MappingTrace;

import com.sap.aii.mapping.api.StreamTransformation;

import com.sap.aii.mapping.api.StreamTransformationConstants;

import com.sap.aii.mapping.api.StreamTransformationException;

import javax.mail.Message;

import javax.mail.MessagingException;

import javax.mail.Session;

import javax.mail.Transport;

import javax.mail.internet.InternetAddress;

import javax.mail.internet.MimeMessage;

import java.util.Properties;

public class SendMailWithAttachment implements StreamTransformation

{

            private MappingTrace trace;

            public void setParameter(Map param)

             {

    if (param != null)

      {

        Object o = param.get(StreamTransformationConstants.MAPPING_TRACE);

        if (o != null && o instanceof MappingTrace)

         {

        trace = (MappingTrace) o;

           }

        }

      }

            public void execute(InputStream in, OutputStream out)throws StreamTransformationException

             {

try

                          {

                                    InputStream stdin = new DataInputStream(in);

                                    stdin.reset();

                                    byte[] buffer = getBytesFromStream(stdin);

                                    String str = new String(buffer);

                                    int index=str.indexOf("<Service>BC_FTP</Service>");

                                    if (index>0)

                                    { out.write(str.getBytes());

                                      out.close();

                                      }

                                    //End of if block

                                    else

                           {

                                    out.write(str.getBytes());

                            out.close();   

                                    SendMailWithAttachment alert=new SendMailWithAttachment();

                                    alert.send("d23ml182.in.ibm.com","sugata.b.majumder@in.ibm.com","LookUp Error","Hi, Message Failed due to Lookup Error.","noreply_PIX@in.ibm.com","/usr/sap/PIX/put/");

                                    }

                                    String fdel= "/usr/sap/PIX/put/Payload_Error.txt";

                                    File f1 = new File(fdel);

                                    f1.delete();

                        }

            catch (IOException e)

                         {

                           e.printStackTrace();

                        }

            finally

            {

                        System.gc();

            }

                        }

            public int getLengthFromStream(InputStream is ) throws

                        IOException{

                        int i = 0;

                        int length = 0;

                        try{

                        while ((i = is.read())> 0){

                        length ++;

                        }

                        }catch (ArrayIndexOutOfBoundsException e) {

                        e.printStackTrace();

                        }

                        return length;

                        }

            public byte[] getBytesFromStream(InputStream is) throws

                        IOException {

                        byte[] bytes = new byte[getLengthFromStream(is)];

                        is.reset();

                        int offset = 0;

                        int tmp = 0;

                        while (offset < bytes.length

                        && (is.read(bytes, offset, offset +

                        (tmp = is.available()))) > 0) {

                        offset += tmp;

                        }

                        if (offset < bytes.length) {

                        throw new IOException("Could not completely read Inputstream");

                        }

                        is.close();

                        return bytes;

                        }

            public void postMail(String mailhst, String recivers, String subject, String messagebody, String from,String filepath) throws MessagingException

            {

                        boolean debug = false;

        Properties props = new Properties();

                        props.put("mail.smtp.host", mailhst);

                        Session session = Session.getDefaultInstance(props, null);

                        session.setDebug(debug);

                        Message msg = new MimeMessage(session);

                        InternetAddress addressFrom = new InternetAddress(from);

                        msg.setFrom(addressFrom);

                        String recipients[] = recivers.split(",");

                        InternetAddress[] addressTo = new InternetAddress[recipients.length];

                        for (int i = 0; i < recipients.length; i++)

                                    addressTo[i] = new InternetAddress(recipients[i]);

                        msg.setRecipients(Message.RecipientType.TO, addressTo);

                        msg.addHeader("MyHeaderName", "myHeaderValue");

                        msg.setSubject(subject);

                        // Create the message part

                          BodyPart messageBodyPart = new MimeBodyPart();

                          // Fill the message

                          messageBodyPart.setText(messagebody);

                          Multipart multipart = new MimeMultipart();

                          multipart.addBodyPart(messageBodyPart);

                          // attachment

                          messageBodyPart = new MimeBodyPart();

                          String filename = filepath+"/"+"Payload_Error.txt";

                          DataSource source = new FileDataSource(filename);

                          messageBodyPart.setDataHandler(new DataHandler(source));

                          messageBodyPart.setFileName(filename);

                          multipart.addBodyPart(messageBodyPart);

                          // Put parts in message

                          msg.setContent(multipart);

                        //msg.setContent(message, "text/plain");

                        Transport.send(msg);

                       

            }

            public void send(String mailhst, String recivers, String subject, String messagebody, String from,String filepath)

            {

            try {

                        this.postMail(mailhst, recivers, subject, messagebody, from, filepath);

            }

            catch (MessagingException mex) {

                        trace.addWarning("send failed, exception: " + mex);

            }

            }

            /*public void deletefile(String file)

{

                          File f1 = new File(file);

                          boolean success = f1.delete();

                          if (!success)

                           {

                          trace.addWarning("Deletion failed.");

                            }

                          else

                            {

                                    trace.addInfo("File deleted.");

                            }

}*/

}         

//class end

Once this is done this operation mapping is included in the below receiver determination-

                                     

Here, the Ignore radio button is chosen as the message should be processed further if no receiver is found. It will not create a failed message in SXMB_MONI and will prevent from re-trying of message.

                

The other operation mapping is included in the below interface determination as part of successful receiver determination case.

                                                 

Testing the Scenario:

Message picked up from the FTP source location and message with correct payload hence no failure in lookup message processed successfully from MONI.

                           

Message processing stopped in MONI as the source payload is wrong and failed in the look up-

                                           

An email notification is received with the payload attachment as below –

                                          

Restriction:

A few restrictions are there for this design-

  1. File is being created using the first Java Mapping in PI application server, this should be deleted in the 3rd step Java mapping.
  2. System.gc() must be called at the end of the Java Program as it involves a I/O operations.
  3. Every Stream should be closed properly.
  4. While testing this scenario in operation mapping level the code for sending mail should be slightly changed with a dummy email address, otherwise it will send mail to the recipients unnecessarily.

2 Comments
Labels in this area