Skip to Content
Personal Insights

Java mapping to download pdf from URL in response and send it as attachment along with response payload.

Okay, So this is the first time I’m writing a blog post on SAP blogs.

For a long time, I was thinking of doing this and looking for the correct topic to start my blogging and then a few days ago I received a requirement where I had to download a pdf from response payload and send it as an attachment along with the response payload.

I was exploring options to do this when I decided to go with Java mapping. At this point, I knew that this is the correct topic where I could share my experience and insight with you.

Functional Requirement:

System A sends a request to retrieve PDF documents, via SAP PO using a SOAP request, In response System B provides download link instead of documents. SAP PO has to download these documents using URLs in the payload and send them as attachments back to System A.

Flow Diagram:

 

Sender Channel : SOAP / Best effort.

Receiver Chanel : SOAP

 

Request : Request is sent to retrieve download URL.

Response : Download URL is returned as a response.

 

Mappings:

No mapping is required for request.

Java mapping is added for response message.

 

Below is the screenshot of Request and Response tested from SOAP UI.

 

As you can see from the field sampleurltodownloadfile, we are retrieving download url to download pdf document.

Below is the Java Code that I have used to do this:

 

package com.sap.downloadfile;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.Attachment;
import com.sap.aii.mapping.api.OutputAttachments;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;

public class CompleteClassCode extends AbstractTransformation {

	private static ArrayList<String> downloadURL = new ArrayList<String>();
	private String fileName = null;
	private String contentType = null;
	//private int contentLength = 0;

	private static final int BUFFER_SIZE = 1024;

	@Override
	public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException {
		try {
			try {
				this.mapping(in, out);
			} catch (ParserConfigurationException | SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void mapping(TransformationInput in, TransformationOutput out)
			throws IOException, ParserConfigurationException, SAXException {

		InputStream inputstream = in.getInputPayload().getInputStream();
		OutputStream outputstream = out.getOutputPayload().getOutputStream();

		OutputAttachments outputAttachments = out.getOutputAttachments();

		String xmlOutputPayload = null;

		// Below method domParser(in, out); is only used for reading the sampleurltodownloadfile
		// for the XML payload and put the value into the ArrayList downloadURL.
		domParser(in, out);

		// Method printOutPutStream(inputstream1) is used to write payload to the
		// output.
		xmlOutputPayload = printOutPutStream(inputstream);

		// Below statement will write the output payload
		outputstream.write(xmlOutputPayload.getBytes());

		for (int i = 0; i < downloadURL.size(); i++) {

			byte[] attachmentContent = new byte[BUFFER_SIZE];

			fileName = downloadURL.get(i).substring(downloadURL.get(i).lastIndexOf("/") + 1,
					downloadURL.get(i).lastIndexOf("?"));

			// Method downloadFile(downloadURL.get(i)) --> does the connection and download
			// file and gives the output as a byte array
			attachmentContent = downloadFile(downloadURL.get(i));

			Attachment attachments = outputAttachments.create(fileName, contentType, attachmentContent);

			outputAttachments.setAttachment(attachments);

			out.getOutputAttachments();

		}
		downloadURL.clear();

	}

	public void domParser(TransformationInput tiIn, TransformationOutput tiOut)
			throws ParserConfigurationException, SAXException, IOException {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

		DocumentBuilder builder = factory.newDocumentBuilder();

		Document document = builder.parse(tiIn.getInputPayload().getInputStream());

		document.getDocumentElement().normalize();

		Element root = document.getDocumentElement();
		System.out.println(root.getNodeName());

		NodeList nList = document.getElementsByTagName("item");
		System.out.println("============================");

		for (int temp = 0; temp < nList.getLength(); temp++) {
			Node node = nList.item(temp);
			System.out.println(""); // Just a separator
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				// Print each employee's detail
				Element eElement = (Element) node;
				System.out.println("URL : " + eElement.getElementsByTagName("sampleurltodownloadfile").item(0).getTextContent());

				downloadURL.add(new String(eElement.getElementsByTagName("sampleurltodownloadfile").item(0).getTextContent()));
			}
		}

	}

	private String printOutPutStream(InputStream inInput) throws IOException {
		String finaloutput = "";
		
		String xmlTag = "<?xml version="1.0" encoding="UTF-8"?>\r\n";
		String soapEnvelopeOpening = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n" + "<SOAP-ENV:Body>\r\n";
		String soapEnvelopeClosing = "</SOAP-ENV:Body>\r\n </SOAP-ENV:Envelope>\r\n";

		StringBuffer sb = new StringBuffer();
		InputStreamReader isr = new InputStreamReader(inInput);
		Reader reader = new BufferedReader(isr);
		int ch;
		while ((ch = inInput.read()) > -1) {
			sb.append((char) ch);
		}
		reader.close();
		String inData = sb.toString();

		finaloutput = xmlTag + soapEnvelopeOpening + inData + soapEnvelopeClosing;

		return finaloutput;
	}

	private byte[] downloadFile(String urlInput) throws IOException {
		byte[] byteContent = new byte[BUFFER_SIZE];

		URL url = new URL(urlInput);

		HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
		int responseCode = httpConn.getResponseCode();

		System.out.println(responseCode == HttpURLConnection.HTTP_OK);

		if (responseCode == HttpURLConnection.HTTP_OK) {

			InputStream connInputStream = httpConn.getInputStream();

			contentType = httpConn.getContentType();
			//contentLength = httpConn.getContentLength();

			// Method downloadFile(url.openStream()) --> downloads the file using only URL,
			// it also returns the byte array.

			byteContent = downloadFile(url.openStream());

			connInputStream.close();

		} else {

			String failedReponse = "Download URL: " + urlInput + "/r/n/nNo file to download. Server replied HTTP code: "
					+ Integer.toString(responseCode);
			byteContent = failedReponse.getBytes();
		}

		httpConn.disconnect();

		return byteContent;
	}

	private byte[] downloadFile(InputStream connectionInput) throws IOException {

		BufferedInputStream bis = new BufferedInputStream(connectionInput);
		ByteArrayOutputStream os = new ByteArrayOutputStream();

		byte[] buffer = new byte[BUFFER_SIZE];
		int count = 0;
		while ((count = bis.read(buffer, 0, BUFFER_SIZE)) != -1) {

			os.write(buffer, 0, count);

		}

		return os.toByteArray();
	}

	public static void main(String[] args) {

	}

}

 

By using the above code, you can download and stream other file formats as well by changing Content-Type.

I hope this helps 🙂

 

Reference Links:

1. How to add attachment using JAVA Mapping (SAP PO) :

https://blogs.sap.com/2015/05/16/how-to-add-attachment-using-java-mapping-sap-po/

2. SAP PI/PO – Java Mapping Create attachments – SFTP :

https://blogs.sap.com/2020/02/09/sap-pi-po-java-mapping-create-attachments-sftp/

2 Comments
You must be Logged on to comment or reply to a post.