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: 
former_member183816
Active Participant
3,427
Scope:
Recently, I came across a specific requirement in SAP PI to implement,

  1. Pick a file from a server.

  2. Call two standard BAPI in a sequence in SAP ECC system.

  3. If first BAPI call fails, ignore it. But if second BAPI call fails, trigger a non-technical beautiful email to user along with payload as attachment.


Why not Alert Framework of SAP PI?
Using alert email, you can't send exact BAPI failure to user. Alert framework generates a default error (below) along with too many technical details which can't be understood by users.



I searched about the requirement on SCN, found this post,
https://scn.sap.com/thread/3743813

Proposed solution in the above thread, is implemented in ECC system, not in PI.
Here's how I designed and implemented everything in PI without troubling our ABAPers.

Design:

 


Implementation:

ESR Objects:

Interfaces:
We will use following 4 interfaces, 1 outbound for receiving file in PI, 2 for BAPI calls and 1 for sending email to users.

File Outbound Interface (To receive file in SAP PI)
BAPI_1 (Import from SAP ECC system, for first BAPI call)
BAPI_2 (Import from SAP ECC system, for second BAPI call)
Mail Inbound Interface (To send email to Users)

Operation Mappings:
We will use 2 operation mappings. One for first BAPI call and one for Second BAPI call as RFC lookup and creating Email package.

1. File to BAPI_1 (Message Mapping: File to BAPI 1 Request)



2. File to BAPI_2 Response and Mail
(Message Mapping: File to BAPI 2 Request for creating BAPI request)
(Message Mapping: BAPI 2 Request to Response for RFC Look up)
(Message Mapping: BAPI 2 Response to Mail for creating Mail package)



a. File to BAPI 2 Request message mapping



b. BAPI 2 Request to Response message mapping



c. BAPI 2 Response to Mail message cum java mapping



I always prefer this approach for java mapping as you can test it right away like your graphical mapping.

Write Java Mapping directly in ESR!

Please find below Java code for parsing BAPI response and creating email package. You need to adjust it as per your requirement.
public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException
{
try{
//https://scn.sap.com/docs/DOC-64656
//Getting reference of output stream to write email package
OutputStream os = out.getOutputPayload().getOutputStream();
InputStream is =in.getInputPayload().getInputStream();

//Dynamic configuration set up
DynamicConfigurationKey KEY_FILENAME =
DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","FileName");

DynamicConfigurationKey KEY_FOLDER =
DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","Directory");

DynamicConfigurationKey KEY_STAMP =
DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","MTime");

DynamicConfiguration conf = in.getDynamicConfiguration();
String fname=conf.get(KEY_FILENAME);
String fdr=conf.get(KEY_FOLDER);
String stmp=conf.get(KEY_STAMP);

//Timestamp conversion from Unix format to simple format
SimpleDateFormat sdf = new SimpleDateFormat("MMMM d, yyyy 'at' h:mm a");
stmp= sdf.format(Long.parseLong(stmp) * 1000);

//CRLF
String CRLF = "\r\n";
String mailS,subj;
boolean err=false; //BAPI Response flag
String fileName=in.getInputParameters().getString("PARAM_FILENAME");//import parameter,Simple Type,xsd:string

//Getting Email Addresses (Parametrized java Mapping)
String fromEmail= in.getInputParameters().getString("PARAM_FROM"); //import parameter,Simple Type,xsd:string, from email address
String toEmail=in.getInputParameters().getString("PARAM_TO");//import parameter,Simple Type,xsd:string, to Email address
String toEmailS=in.getInputParameters().getString("PARAM_TO_S");//import parameter,Simple Type,xsd:string, to Email address for successful case

//Adding trace
getTrace().addInfo("Copying input payload");

/*
Sample BAPI Response XML for the reference
<RETURN>
<item>
<TYPE>E</TYPE>
<ID>00</ID>
<NUMBER>001</NUMBER>
<MESSAGE>Order: entry 00007 is already technically completed</MESSAGE>
<LOG_NO />
<LOG_MSG_NO></LOG_MSG_NO>
<MESSAGE_V1></MESSAGE_V1>
<MESSAGE_V2></MESSAGE_V2>
<MESSAGE_V3></MESSAGE_V3>
<MESSAGE_V4 />
<PARAMETER>PAR1</PARAMETER>
<ROW>0</ROW>
<FIELD />
<SYSTEM>SAPPI</SYSTEM>
</item>
</RETURN>

*/
//Initializing document builder for parsing BAPI response
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(in.getInputPayload().getInputStream());

String poi=doc.getElementsByTagName("NUMBER").item(0).getTextContent(); // Getting document number from "NUMBER" node in incoming xml

NodeList ret = doc.getElementsByTagName("RETURN"); //Extracting Return type from BAPI response under "RETURN" node
Element eret = (Element) ret.item(0);

NodeList itL=eret.getElementsByTagName("item");
String[] ty= new String[itL.getLength()];
String[] text= new String[itL.getLength()];
String[] par= new String[itL.getLength()];
//Looping item nodes in case of multiple rows, returned from BAPI
for (int i = 0; i < itL.getLength(); i++) {
Node itN= itL.item(i);
Element eit = (Element) itN;
ty[i]=eit.getElementsByTagName("TYPE").item(0).getTextContent(); //Getting Response type "E", "I", "", "S"
if(ty[i].equals("E") || ty[i].equals("I"))
{
err=true;
text[i]=eit.getElementsByTagName("MESSAGE").item(0).getTextContent(); // Getting Reason of failure
par[i]=eit.getElementsByTagName("PARAMETER").item(0).getTextContent();// Parameter due to which BAPI call failed
}
}
if(err)
{
//Setting Mail subject, address, content in case of failure response
subj="interface FAILURE notification";
mailS="Interface triggered has failed for document number"+CRLF
+CRLF+"Number: "+poi+CRLF
+CRLF+"Error Message: ";
for (int j = 0; j < itL.getLength(); j++)
{
if(ty[j].equals("E") || ty[j].equals("I"))
{
mailS=mailS+CRLF+text[j]+CRLF;
// +"Due to Parameter: "+par[j]+CRLF;
}
}
mailS=mailS+CRLF
+"Refer to attachment for more details"+CRLF+CRLF
+"File ID: "+fname+CRLF
+"Directory: "+"testdirectory/Outbound"+CRLF
+"Time Stamp: "+stmp+CRLF+CRLF+CRLF+CRLF
+"Please investigate and contact to reprocess failed message if required.";
}
else
{
//Setting Mail subject, address, content in case of successful response
subj="interface SUCCESS notification";
mailS="Interface triggered has processed successfully for document number"+CRLF
+CRLF+"Number: "+poi+CRLF+CRLF
+"Refer to attachment for more details"+CRLF+CRLF
+"File ID: "+fname+CRLF
+"Directory: "+"testdirectory/Outbound"+CRLF
+"Time Stamp: "+stmp;
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();//ByteArrayOutputStream to write incoming BAPI response as attachment
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
//Creating Attachment
getTrace().addInfo("Attachment created");
if(!err)
toEmail=toEmailS;

String boundary="--AaZz";
String emailPackage= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<ns:Mail xmlns:ns=\"http://sap.com/xi/XI/Mail/30\">"
+ "<Subject>" +subj+"</Subject>"
+ "<From>" + fromEmail + "</From>"
+ "<To>" + toEmail + "</To>"
+ "<Content_Type>multipart/mixed; boundary=\""
+ boundary
+ "\"</Content_Type>"
+ "<Content>";
os.write(emailPackage.getBytes());//Writing Email Package in output stream
// create the declaration of the MIME parts
//First part
emailPackage = "--" + boundary + CRLF
+ "Content-Type: text/plain; charset=UTF-8" + CRLF
+ "Content-Disposition: inline" + CRLF + CRLF
+ mailS + CRLF + CRLF

//Second part
+ "--" + boundary + CRLF
+ "Content-Type: application/xml; name=" + fileName + CRLF
+ "Content-Disposition: attachment; filename=" + fileName + CRLF + CRLF;
os.write(emailPackage.getBytes());
String sbuf = baos.toString("UTF-8");
// replace all control characters with escape sequences
sbuf = sbuf.replaceAll("&", "&amp;");
sbuf = sbuf.replaceAll("\"", "&quot;");
sbuf = sbuf.replaceAll("'", "&apos;");
sbuf = sbuf.replaceAll("<", "&lt;");
sbuf = sbuf.replaceAll(">", "&gt;");
os.write(sbuf.getBytes("UTF-8"));
emailPackage = CRLF + CRLF +"--" + boundary + "--" + CRLF;
os.write(emailPackage.getBytes());
// finish mail package
os.write("</Content></ns:Mail>".getBytes());

os.flush(); //Flushing output stream
os.close(); //Closing output stream

}
catch (Exception e)
{
throw new StreamTransformationException(e.getMessage());
}
}

You need to check ASMA (Adapter specific message attributes) in your sender file channel and define adapter type import parameter in order to get file name, directory during mapping execution.

Integration Directory Configuration:

Design an ICO in ID,

Inbound processing: Select your outbound interface, sender file channel.
Receiver: Select appropriate receiver of your configuration.
Receiver interface: Call Operation mapping in sequence if required. Configure parameter as per your mapping, for RFC lookup channel, email addresses, attachment name.



Outbound processing: for first BAPI call.



Outbound processing: for Email interface, BAPI call happens in mapping lookup.



Channel configurations:

Email: “Use Email package” should be checked and content encoding should be “none”.



 

RFC: You have to add Successful RETURN TYPE as E, I, S in advanced mode accordingly, so that you can capture both successful and failure responses during lookup.




Test:
Sample email generated from above setup.





Credits and references:

I referred following blog of stefan.grube for Email package creation and mail adapter settings.

https://blogs.sap.com/2007/04/17/xi-mail-adapter-an-approach-for-sending-emails-with-attachment-with...

I also referred few other blogs for writing java code.

https://blogs.sap.com/2014/04/02/file-content-conversion-in-esr-using-java-mapping/

https://blogs.sap.com/2015/06/16/creating-multiple-files-zipping-sending-as-email-attachments-using-...

Please leave your doubts and feedback in the comment section. I will try to clarify them as soon as I see them.

Regards,
Ambuj
1 Comment
Labels in this area