In this doucment, I will show how we can zip the incoming attachments and create a new zip attachment during mapping step. We can also remove the original incoming attachments if they are not required. The concept is applicable from PI7.1 version onwards.
Create a java mapping with below code and use it as first mapping in your operation mapping step.
Java Mapping Code
import java.io.*;
import java.util.Map;
import java.util.HashMap;
import java.util.*;
import java.util.zip.*;
import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.api.*;
import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;
// import com.sap.aii.mapping.api.StreamTransformation;
// import com.sap.aii.mapping.api.StreamTransformationConstants;
import com.sap.aii.mapping.api.StreamTransformationException;
public class AttachmentsZipJM extends AbstractTransformation {
private static final DynamicConfigurationKey contentIDSKey = DynamicConfigurationKey.create("http://test.com", "contentIDS");
public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException
{
try
{
DynamicConfiguration conf = (DynamicConfiguration) in.getDynamicConfiguration();
// get message ID
String msgID = (String) in.getInputHeader().getMessageId();
String s = null;
int len = 0;
Object[] arrayObj = null;
byte[] buffer = new byte[1024];
byte[] attachmentBuffer = new byte[1024];
String attachmentID = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry anEntry = null;
InputStream is = (InputStream) in.getInputPayload().getInputStream();
while ((len = is.read(buffer)) > 0)
{
out.getOutputPayload().getOutputStream().write(buffer, 0, len);
}
InputAttachments inputAttachments = in.getInputAttachments();
if(inputAttachments.areAttachmentsAvailable())
{
//gets the attachmentIds and store it in an Object array
Collection<String> collectionIDs = inputAttachments.getAllContentIds(true);
arrayObj = collectionIDs.toArray();
//Object[] arrayObj = collectionIDs.toArray();
String contentIDS = "";
//Loops at the input attachments to get the content of the attachment and then write it to zip output stream wrapper.
for(int i =0;i<arrayObj.length;i++)
{
attachmentID =(String)arrayObj[i];
contentIDS = contentIDS + (i+1) + ") " + attachmentID + "; ";
Attachment attachment = inputAttachments.getAttachment(attachmentID);
byte[] attachmentBytes = attachment.getContent();
zos.putNextEntry(new ZipEntry(attachmentID));
zos.write(attachmentBytes);
zos.closeEntry(); //Close each zipentry after writing it to stream
//remove each attachment if required. Uncommonent below line
//out.getOutputAttachments().removeAttachment(attachmentID);
}
zos.close(); //Close Zip Stream
conf.put(contentIDSKey, contentIDS);
}
Attachment newopAttachment = out.getOutputAttachments().create(msgID + ".zip", baos.toByteArray());
out.getOutputAttachments().setAttachment(newopAttachment);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The same can be achieved in graphical mapping using below code. Use the UDF in between source and target root nodes. Ensure to explicitly mention java.util.zip.* package under import statements of UDF function.
Graphical Mapping UDF Code
String attachmentID = null;
String msgID = null;
String contentIDS = "";
java.util.Map map;
AbstractTrace trace;
//gets the input attachment from the source message
GlobalContainer globalContainer = container.getGlobalContainer();
InputAttachments inputAttachments = globalContainer.getInputAttachments();
OutputAttachments outputAttachments = globalContainer.getOutputAttachments();
trace = container.getTrace();
map = globalContainer.getParameters();
msgID = (String) map.get(StreamTransformationConstants.MESSAGE_ID);
trace.addInfo("Message ID:" + msgID);
DynamicConfiguration conf = (DynamicConfiguration) map.get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey contentIDSKey = DynamicConfigurationKey.create("http://test.com", "contentIDS");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
try
{
//checks for the availability of attachments in the input message
if(inputAttachments.areAttachmentsAvailable())
{
trace.addInfo("Attachments Available");
//gets the attachmentIds and store it in an Object array
Collection<String> CollectionIDs = inputAttachments.getAllContentIds(true);
Object[] arrayObj = CollectionIDs.toArray();
//Loops at the input attachments to get the content of the attachment
for(int i =0;i<arrayObj.length;i++)
{
attachmentID =(String)arrayObj[i];
contentIDS = contentIDS + (i+1) + ") " + attachmentID + "; ";
trace.addInfo("Attachment no: " + (i+1) + " & Name: " + attachmentID);
Attachment attachment = inputAttachments.getAttachment(attachmentID);
byte[] attachmentBytes = attachment.getContent();
trace.addInfo("Creating Zip Entry for attachmet no: " + (i+1));
zos.putNextEntry(new ZipEntry(attachmentID));
zos.write(attachmentBytes);
zos.closeEntry(); //Close each zipentry after writing it to stream
//remove each attachment if required. Uncommonent below
//trace.addInfo("Removing Attachment no: " + (i+1) + " & Name: " + attachmentID);
//outputAttachments.removeAttachment(attachmentID);
}
zos.close();
conf.put(contentIDSKey, contentIDS);
trace.addInfo("Creating new Zip Attachment: " + msgID + ".zip");
Attachment newopAttachment = outputAttachments.create(msgID + ".zip", baos.toByteArray());
outputAttachments.setAttachment(newopAttachment);
}
}
catch (Exception e)
{
e.printStackTrace();
}
return var1; //return “1”;
I tested a sample SOAP to Mail scenario with above code and the results are as below.
In RWB for mail receiver adapter,
The zipping/unzipping of attachments can also be achieved at adapter level using PayloadZipBean module.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
10 | |
9 | |
5 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 |