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: 
dilipkkp2412
Contributor

Overview:



  • In this blog, we will see, how any pdf file of "SAP-Ecc-System" can be send to Sharepoint via SAP-PI.

  • Sharepoint provides REST API details which can be used to post file in specific directory of Sharepoint.

  • Using SAP-PI's interface pdf file will be send to Sharepoint over these REST API details.


About SAP-PI's interface design:



  • To acheive above, we will design a SAP-PI interface “Outbound Asynchronous File-to-File scenario”.

  • Pdf file will be made available by respective SAP-ECC’s program in to specific "SAP Ecc's Application directory".

  • Using SAP-PI’s Sender-File-Adapter (comm. channel), the pdf files will be picked up from source directory one by one.

  • Using a JavaMap program configured in the same scenario, read pdf file will be send to Sharepoint with the same file naming conventions.

  • Receiver-File-Adapter (comm. channel) will generate a constant dummy file in sap app directory with overwrite feature.


Functionality of JavaMap program will be as follows:



  • This JavaMap uses a resource xml file where Sharepoint REST API details are present.

  • Get file (which was read using Sender-File-Adapter) as an input stream into JavaMap program and convert it to ByteArrayStream

  • Using Dynamic Configuration Variable, get original file Name.

  • Read Sharepoint REST-API details from resource file

  • And send pdf ByteArrayStream to SharePoint REST details with same filename.

  • While accessing SharePoint, first we get access token then we post Sharepoint-REST.


Pre-requisites for JavaMap:



  • JavaMap will be developed using Eclipse.

  • Standard external Jar file required for JavaMap:

    • json-simple-1.1.1.jar      (this is required in both Eclipse and in SAP-PI’s Integration Repository which can be imported inside a new Imported_Archive of same namespace of scenario)

    • aii_map_api.jar              (this is required only in Eclipse)



  • And post completion, it will be exported as '.jar' file which can be used in SAP-PI's respective interface


SAP-PI Scenario Development Steps:



  • Steps in "Enterprise Services (Repository) Builder":

    • Create one dummy DataType only one input element

    • Create one message type referring above dummy datatype

    • Create one Service Interface Inbound asynchronous referring above message type, say “SI_IN”

    • Create one Service Interface Outbound asynchronous referring above message type, say “SI_OUT”

    • Create one "Imported Archive" to import external jar file "json-simple-1.1.1.jar"

    • Create 2nd "Imported Archive" to import this blog's JavaMap example program

    • Create one Operation Mapping, use in Source operation select “SI_OUT” and in Target operation select “SI_IN”. Inside Mapping program select 2nd "Imported Archive".



  • Steps in "Integration (Directory) Builder"

    • According to above config of "Repository", configure Integrated Directory's Scenario

    • Two communication channels required

      • one Sender File-Adapter:    will be used to read '.pdf' files from SAP's directory

      • one Receiver File-Adapter:  its job is to complete the scenario config only, it will keep on over-writing same file in sap's directory for each file-transfer-trigger with fix dummy "fileName".






 

SAP PI JavaMap program to post pdf file in Sharepoint :



  • JavaMap project view in Eclipse:


  • Resource file "Service_Credentials.xml", which is been used in JavaMap to refer for Sharepoint-REST-API details:


  • <?xml version="1.0" encoding="UTF-8"?>
    <ServiceData>
    <SharePoint_REST>
    <client_Id>clientIdShp</client_Id>
    <client_secret>shpSecret</client_secret>
    <tenant_Id>shpTenant</tenant_Id>
    <client_Domain>ShpHost (without sharepoint.com)</client_Domain>
    <SharePoint_SiteURL>https://host/teams/SPdev/AlertsCount</SharePoint_SiteURL>
    <SharePoint_AccessTokenUrl>https://accounts.accesscontrol.windows.net/(tenantId)/tokens/OAuth/2</SharePoint_AccessTokenUrl>
    <SharePoint_FolderName>folderName</SharePoint_FolderName>
    </SharePoint_REST>
    </ServiceData>


  • JavaMap Source Code:


  • import java.io.BufferedReader;
    import java.io.ByteArrayOutputStream;
    import java.io.DataOutputStream;
    import java.io.FileInputStream;

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.StringReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.HashMap;
    import java.util.Map;

    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;

    import org.json.simple.JSONObject;
    import org.json.simple.parser.JSONParser;
    import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.InputSource;
    import org.xml.sax.SAXException;

    import com.sap.aii.mapping.api.AbstractTrace;
    import com.sap.aii.mapping.api.DynamicConfiguration;
    import com.sap.aii.mapping.api.DynamicConfigurationKey;
    import com.sap.aii.mapping.api.StreamTransformation;
    import com.sap.aii.mapping.api.StreamTransformationConstants;
    import com.sap.aii.mapping.api.StreamTransformationException;


    public class BackLogPdfToShp implements StreamTransformation{
    /*
    public static void main(String[] args) {
    //This function helps to test JavaMap inside eclipse
    try{
    BackLogPdfToShp myClass = new BackLogPdfToShp();
    FileInputStream in = new FileInputStream("D:/xyz/TestInput.pdf");
    FileOutputStream out = new FileOutputStream("d:/xyz/TestLog.xml");
    myClass.execute(in, out);
    }catch (Exception e){
    e.printStackTrace();
    }
    }
    */

    private static Map param;
    public void setParameter(Map map)
    {
    param = map;
    if (param == null){
    param = new HashMap();
    }
    }
    private static AbstractTrace trace = null;
    private static String mapTrace = "";
    public void execute(InputStream in, OutputStream out) throws StreamTransformationException {
    /**
    * This function gets "read pdf file" as an inputStream and post it to SharePoint
    */

    try{
    trace = (AbstractTrace) param.get(StreamTransformationConstants.MAPPING_TRACE);
    mapTrace = "";
    mapTrace = mapTrace + " Begin of JavaMap 'BackLogPdfToShp()' " + "\n";

    //Get fileName using DynamicConfigurationVariables
    String fileName = getFileNameUsingDynmConfig();
    mapTrace = mapTrace + " File found with name: " + fileName + "\n";

    //Read pdf file from PI's File Adapter
    mapTrace = mapTrace + " convert Pdf(inputStream) To ByteArray .. " + "\n";
    byte[] bytes = convertInputstreamToByte(in); //convert Pdf(inputStream) To ByteArray ..

    //Get SharePoint access token
    mapTrace = mapTrace + " Read Sharepoint REST details from file 'Service_Credentials.xml'" + "\n";
    readServiceDetails_FromXml();

    mapTrace = mapTrace + " Get Sharepoint accesstoken... " + "\n";
    String accesstoken = SharePoint_getAccessToken();

    //Write pdf file into Sharepoint
    mapTrace = mapTrace + " Write file into Sharepoint " + "\n";
    String shpResponse = SharePoint_WriteFile(accesstoken, bytes, fileName);

    //Transform Output Document
    String outputXML = "<?xml version=\"1.0\"?>"
    + "\n" +"<JavaMap_Log>"
    + "\n" +"<SharePoint_Response><![CDATA[" + shpResponse + "]]></SharePoint_Response>"
    + "\n" +"<JavaMap_Trace><![CDATA[" + mapTrace + "]]></JavaMap_Trace>"
    + "\n" +"</JavaMap_Log>";
    Document docOut = convertStringToDocument(outputXML);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transform = tf.newTransformer();
    transform.transform(new DOMSource(docOut), new StreamResult(out));

    }catch (Exception e) {
    trace.addInfo("||Exception in JavaMap 'BackLogPdfToShp': " + e.getMessage());
    mapTrace = mapTrace + " " + e.getMessage();
    }
    //System.out.println(mapTrace);
    }

    private static String getFileNameUsingDynmConfig(){
    /**
    * This function gets file name of read file via 'Sender-File-Adapter' using DynamicConfiguration variable
    */
    String fileName = "";
    try
    {
    DynamicConfiguration conf = (DynamicConfiguration)param.get("DynamicConfiguration");
    DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File", "FileName");
    fileName = conf.get(key); //get File name
    }catch(Exception ex){
    ;
    }
    return fileName;
    }

    private byte[] convertInputstreamToByte(InputStream in) {
    /**
    * This function converts InputStream to ByteArray
    */
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buf = new byte[1024];
    try {
    for (int readNum; (readNum = in.read(buf)) != -1;) {
    bos.write(buf, 0, readNum);
    }
    } catch (IOException ex) {
    mapTrace = mapTrace + " " + ex.getMessage();
    }
    byte[] bytes = bos.toByteArray();
    return bytes;
    }

    private static String shp_clientId = "";
    private static String shp_clientSecret = "";
    private static String shp_tenantId = "";
    private static String shp_clientDomain = "";
    private static String shpUrl_AccessToken= "";
    private static String shp_FolderName = "";
    private static String shpUrl_SiteURL = "";

    private void readServiceDetails_FromXml() throws IOException, ParserConfigurationException, SAXException{
    /**
    * This function read SharePoint-REST API details mentioned in resource file "Service_Credentials.xml"
    */
    //Get reference of ResourceFile 'Service_Credentials.xml'
    InputStream is_ShpCrd = getClass().getResourceAsStream("Service_Credentials.xml");

    //Parse it to Document
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
    Document xmlDocCrd = dbBuilder.parse(is_ShpCrd); //Parse input to create document tree

    //----Start: Get SharePoint Credentials from XmlFile ------
    NodeList ndList_shp = xmlDocCrd.getElementsByTagName("SharePoint_REST");
    for(int i1 = 0; i1 < ndList_shp.getLength(); i1++){
    Node nd_1 = ndList_shp.item(i1);
    for(Node nd_2 = nd_1.getFirstChild(); nd_2 != null; nd_2 = nd_2.getNextSibling()){
    if(nd_2.getNodeName().equals("client_Id")){
    if(nd_2.getFirstChild() != null){
    shp_clientId = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<client_Id> is empty" + "\n";
    }
    }
    if(nd_2.getNodeName().equals("client_secret")){
    if(nd_2.getFirstChild() != null){
    shp_clientSecret = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<client_secret> is empty" + "\n";
    }
    }
    if(nd_2.getNodeName().equals("tenant_Id")){
    if(nd_2.getFirstChild() != null){
    shp_tenantId = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<tenant_Id> is empty" + "\n";
    }
    }
    if(nd_2.getNodeName().equals("client_Domain")){
    if(nd_2.getFirstChild() != null){
    shp_clientDomain = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<client_Domain> is empty" + "\n";
    }
    }
    if(nd_2.getNodeName().equals("SharePoint_AccessTokenUrl")){
    if(nd_2.getFirstChild() != null){
    shpUrl_AccessToken = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<SharePoint_AccessTokenUrl> is empty" + "\n";
    }
    }
    if(nd_2.getNodeName().equals("SharePoint_SiteURL")){
    if(nd_2.getFirstChild() != null){
    shpUrl_SiteURL = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<SharePoint_SiteURL> is empty" + "\n";
    }
    }
    if(nd_2.getNodeName().equals("SharePoint_FolderName")){
    if(nd_2.getFirstChild() != null){
    shp_FolderName = nd_2.getFirstChild().getNodeValue();
    }else{
    mapTrace = mapTrace + "<SharePoint_FolderName> is empty" + "\n";
    }
    }
    }
    }
    //----End : Get SharePoint Credentials from XmlFile ------

    }

    private static String SharePoint_getAccessToken(){
    /**
    * This function is to get SharePoint Access token.
    * SharePoint REST-URL to get access token is:
    * URL : https://accounts.accesscontrol.windows.net/<tenantID>/tokens/OAuth/2
    METHOD : GET
    */

    String accessToken = "";
    try {
    mapTrace = mapTrace +" ||...SharePoint Client Id: "+ shp_clientId+ "\n";
    mapTrace = mapTrace +" ||...SharePoint Tenant Id: "+ shp_tenantId+ "\n";
    mapTrace = mapTrace +" ||...SharePoint Client Secret: "+ shp_clientSecret+ "\n";
    mapTrace = mapTrace +" ||...SharePoint Client Domain: "+ shp_clientDomain+ "\n";

    //SharePoint AccessToken URL
    String wsURL = shpUrl_AccessToken;
    mapTrace = mapTrace +" ||...SharePointAccessToken URL: " + wsURL+ "\n";

    //Create HttpConenction
    URL url = new URL(wsURL);
    URLConnection connection = url.openConnection();
    HttpURLConnection httpConn = (HttpURLConnection) connection;

    //Set header
    httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);
    httpConn.setRequestMethod("POST");

    //Prepare RequestData
    String jsonParam =
    "grant_type=client_credentials" +
    "&client_id="+shp_clientId+"@"+shp_tenantId +
    "&client_secret=" + shp_clientSecret +
    "&resource=00000003-0000-0ff1-ce00-000000000000/"+ shp_clientDomain + ".sharepoint.com@" + shp_tenantId;

    //Send Request
    DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream ());
    wr.writeBytes(jsonParam);
    wr.flush();
    wr.close();

    //Read the response
    String httpResponseStr = "";
    InputStreamReader isr = null;
    if (httpConn.getResponseCode() == 200) {
    isr = new InputStreamReader(httpConn.getInputStream());
    } else {
    isr = new InputStreamReader(httpConn.getErrorStream());
    }
    BufferedReader in = new BufferedReader(isr);
    String strLine = "";
    while ((strLine = in.readLine()) != null) {
    httpResponseStr = httpResponseStr + strLine;
    }

    //Extracting accessToken from httpResponseStr which is a JSON format string
    /*
    Sample HTTP Response String(httpResponseStr) is as below:
    {"token_type":"Bearer","expires_in":"3599","not_before":"1509537628","expires_on":"1509541528","resource":"","access_token":"xyz"}
    */
    JSONParser parser = new JSONParser(); //Jar file reference required: json-simple-1.1.1.jar
    JSONObject jsonObj = (JSONObject)parser.parse(httpResponseStr);
    accessToken = (jsonObj.get("access_token")).toString(); //get value of element

    mapTrace = mapTrace + " ||...SharePointAccessToken found as: " + accessToken + "\n";
    } catch (Exception e) {
    mapTrace = mapTrace + " " + e.getMessage();
    }
    return accessToken;
    }

    private static String SharePoint_WriteFile(String accessToken, byte [] requestStr, String fileName) throws IOException{
    /**
    * This function is to POST input to SharePoint as a file.
    * SharePoint-REST-URL Details to Write a file is as below:
    URL : http://<siteurl>/_api/web/GetFolderByServerRelativeUrl('/FolderName')/Files/add(url='FileName',overwrite=false)
    METHOD : POST
    BODY : "Contents of file"
    Headers :
    Authorization: "Bearer " + accessToken
    X-RequestDigest: form digest value
    content-length:length of post body
    */

    String responseStr = "";
    try {
    String wsUrl = shpUrl_SiteURL + "/_api/web/GetFolderByServerRelativeUrl('"
    + shp_FolderName + "')/Files/add(url='"
    + fileName +"',overwrite=true)";


    mapTrace = mapTrace + "\n" + " ||...URL: " + wsUrl;

    //Create HttpURLConnection
    URL url = new URL(wsUrl);
    URLConnection connection = url.openConnection();
    HttpURLConnection httpConn = (HttpURLConnection) connection;

    //Set Header
    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);
    httpConn.setRequestMethod("POST");
    httpConn.setRequestProperty("Authorization", "Bearer " + accessToken);

    //Send Request
    DataOutputStream dos = new DataOutputStream(httpConn.getOutputStream ());
    dos.write(requestStr); //Writing PDF byte[] Stream
    dos.flush();
    dos.close();

    //Read the response.
    if (httpConn.getResponseCode() == 200) {
    responseStr = " ||...File '"+ fileName + "' has been written into SharePoint with Success-HTTP-ResponseCode: "+ httpConn.getResponseCode() +"\n";
    }else{
    responseStr += " ||...Response-" + httpConn.getResponseCode() + " " + httpConn.getResponseMessage() +": Error while writing file '"+ fileName + "' in SharePoint.\n";
    }
    mapTrace = mapTrace + "\n" + responseStr;
    } catch (Exception e) {
    mapTrace = mapTrace + "\n" + " ||...Error while Posting file to SharePoint: "+ e.getMessage() + " [JavaFunction SharePoint_WriteFile()]\n";
    }
    return responseStr;
    }

    private static Document convertStringToDocument(String xmlStr) {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder;
    try
    {
    builder = factory.newDocumentBuilder();
    Document doc = builder.parse( new InputSource( new StringReader( xmlStr ) ) );
    return doc;
    } catch (Exception e) {
    mapTrace = mapTrace + " " + e.getMessage();
    }
    return null;
    }
    }


  • While exporting file (.jar), make sure resource file is present in jar:



 

Testing of JavaMap from PI Scenario:

  • Once Sender-File-Adapter picks up file from  logs which picks up file from sap directory, JavaMap gets invoked and as per its functionality it behaves to post same pdf file in Sharepoint. Its step-by-step process can be understood from following log screen

  • JavaMap custom log (can be seen from SXMB_MONI of SAP-PI)


  • File availability in Sharepoint post javaMap execution



 

<<<<< Parent blog reference.....  Integrate SharePoint using SAP PI
13 Comments
0 Kudos
Hi Dilip,

Thanks for the nice work.

I followed your blog not getting Access Token. Do we need to Grant Permissions to Add-In from SharePoint Online to our PI system before calling ?

BR,

 
dilipkkp2412
Contributor
0 Kudos
Dear Priya,

If you are getting following error w.r.t. permissions while fetching AccessToken,

  • "Access denied. You do not have permission to perform this action or access this resource"


Then consult your SharePoint-Team to follow following help-link, where "Write-Permission" need to be given to client-id/app-id:

 

Regards,

Dilip
former_member254404
Participant
0 Kudos
Hi,

Have you tried to write the PDF file using REST adapter?

Regards

Prasad U
former_member254404
Participant
0 Kudos
We are able to connect and write the file using Standard REST adapter except PDF files. Is there any way to send base64 format to write the PDF
dilipkkp2412
Contributor
0 Kudos
Hi Sriram,

I haven't yet tried with REST adapter, but its good you tried to write file successfully.

About base64, I have to check, not yet tried.

 

Thanks & Regards,

Dilip

 
former_member254404
Participant
0 Kudos
Hi Dilip,

we followed the same Http Connection steps as mentioned in SharePoint_WriteFile() Method.

But we are still getting the response Code as "Response-400 Bad Request: Error while writing file".

Please provide some solution on this error.

Thanks & Regards,

Kavitha.G

 
dilipkkp2412
Contributor
0 Kudos
Hi Sriram,

In your code, plz chk below:

  • pdf input-Stream and its byte[] conversion which is input for FN SharePoint_WriteFile()

  • SharePoint URL pattern

  • and your SharePoint Client ID should have Write Permission


 

Thanks & regards,

Dilip

 
former_member607993
Contributor
0 Kudos
 

dilipkkp2412

 

Is there any way to store and retrieve the tokens in SAP PO?
dilipkkp2412
Contributor
0 Kudos
Hi Rajesh,

Currently I'm not aware if any std. functionality is present in SAPPO.

We can think of storing tokens in some file if it has expiry more than 30 mins. And read it from file having last time stamp .

 

Thanks & Regards,

Dilip

 
former_member697857
Discoverer
0 Kudos
Hello Sriram,

Even i have a similar requirement to send a csv file to sharepoint Url.

Tried with standard rest but no luck.

Can you please provide the steps?

Thanks,

Glory.
former_member202642
Participant
0 Kudos
Hi Sriram,

I have a requirement to pick and write a text file in Sharepoint via REST adapter using access token.

But I am getting error 401 as unauthorized.

Please help so I will be able to write the file.

Thanks,

Aamir
dilipkkp2412
Contributor
0 Kudos
Hi Amir,

Please check below blog link you will get example of Read/Write into SharePoint via REST-API.

https://blogs.sap.com/2018/08/26/integrate-sharepoint-using-sap-pi/

Thanks & Regards,

Dilip
dilipkkp2412
Contributor
0 Kudos
Hi Glory,

Please check below blog link you will get example of Read/Write into SharePoint via REST-API.

https://blogs.sap.com/2018/08/26/integrate-sharepoint-using-sap-pi/

Thanks & Regards,

Dilip
Labels in this area