Disclaimer

Please note that in addition to the SCN Terms of Use, the following terms and conditions govern your use of any sample code or sample applications.  Sample code and sample applications are provided only as examples and for illustrative purposes. SAP sample code and sample applications are NOT FOR PRODUCTION OR COMMERCIAL USE, unless otherwise specifically noted.

SAP grants you a nonexclusive copyright license to use any sample code or sample applications to generate the same or similarly functioning code/applications for internal testing and evaluation. You may not demonstrate, test, examine, evaluate or otherwise use them in a live operating environment, or with data that has not been sufficiently backed up. You may not rent, lease, lend, or resell SAP sample code or sample applications.  All sample code and sample applications are provided “AS IS” without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.

How to share your documents from ABAP with SAP Mobile Documents

In this article we will explain how you can develop an ABAP client for SAP Mobile Documents. This client will be able to create a share with a public link and upload documents from your ABAP system into the share on SAP Mobile Documents. This article is part of the step-by-step Implementation and Integration Guide for SAP Mobile Documents.

Prerequisites

For the scenario in this article you need an ABAP system and a SAP Mobile Documents system. The ABAP sample code runs on an ABAP system with SAP_BASIS 7.40. The SAP Mobile Documents system must allow sharing. This setting can be configured in the administration tool of SAP Mobile Documents.

The ABAP client will communicate with the SAP Mobile Documents server via the CMIS protocol. CMIS is an open standard. You can find the specification on: CMIS Specification, Version 1.1.

Overview

The sample code for our ABAP client consists of the following objects:

  • an ABAP class ZCL_DEMO_SHARING_SERVICE,
  • an ABAP exception class ZCX_DEMO_SHARING_EXCEPTION,
  • a report ZDEMO_SHARING_CLIENT,
  • an XSL transformation ZDEMO_PARSE_REPOSITORY_INFOS,
  • and an XSL transformation ZDEMO_PARSE_CREATE_SHARE_RESP.


The class ZCL_DEMO_SHARING_SERVICE is the main part of the client. It offers methods for the following tasks:

  • Read information about the repositories of the SAP Mobile Documents system
  • Create a share in the sharing repository
  • Create a public link for the share
  • Upload a document into the share

The report ZDEMO_SHARING_CLIENT demonstrates how to call these methods one after another. When you execute the report, it will create a new share with a sample document in it, and the share can be accessed with a public link. Finally, the report opens a browser with this public link.

The two XSL transformations ZDEMO_PARSE_REPOSITORY_INFOS and ZDEMO_PARSE_CREATE_SHARE_RESP parse the HTTP responses that the SAP Mobile Documents server sends back to the ABAP system.


The sample code is attached at the end of this article. There is also a webinar: How to integrate your ABAP documents into SAP Mobile Documents.

Part 1: The report ZDEMO_SHARING_CLIENT

The report ZDEMO_SHARING_CLIENT starts with a selection screen (listing 1, lines 4-9) where you can enter values for the following parameters:

Parameter Description
name Name of the share.
desc Description of the share.
days Number of days until the public link of the share expires.
enup A boolean. If true, then a user who accesses the share with the public link is allowed to make changes.
pass Password to access the share with the public link.
dest An SM59 destination to the Mobile Documents server.

The field for parameter pass is a password field (lines 19-25).

In line 29 we create an instance of the ZCL_DEMO_SHARING_SERVICE class. The constructor gets the name of the SM59 destination. It uses this destination to create an instance of IF_HTTP_CLIENT, such that it can communicate with the SAP Mobile Documents server. Next, the constructor sends the first request to the server to read the repository information. This is explained in part 2. The repository information are needed for the subsequent steps.

In line 31 we create a share with the given name and description. The CREATE_SHARE method is explained in part 3. It returns the object ID of the new share, which we need for the steps that follow. At this point the share is still empty and does not yet have a public link.

Listing 1: Report ZDEMO_SHARING_CLIENT

/wp-content/uploads/2015/01/report_1_628668.png

Next we create the public link (listing 2, line38) and determine the URL for public access (line 44). This is explained in part 4.

In line 46 we upload a small XML document to the share. In this example the file content is hard-coded. Of course, the file content might come from another source. The CREATE_DOCUMENT method is explained in part 5. Finally we close the connection to the server (line 52) and open the public link in a browser (line 54). This will open the public web UI of Mobile Documents.

Listing 2: Report ZDEMO_SHARING_CLIENT continued

/wp-content/uploads/2015/01/report_2_628670.png

Connection to the SAP Mobile Documents Server

In order to create a share and upload documents into it, the ABAP system needs a connection to the SAP Mobile Documents server. We use an HTTP connection. The connection data is configured in a destination in transaction SM59 (Configuration of RFC Connections).

  1. Create a destination in transaction SM59 of type G (HTTP Connections to External Server).
  2. In the Technical Settings of the destination enter the target host and the service number (port) of the SAP Mobile Documents server.
  3. In the Logon & Security section define a logon procedure. The user that logs on will be the owner of the shares that are being created.
  4. In the Special Options section accept cookies.

Part 2: How to retrieve repository information

In this part we ask the SAP Mobile Documents system about its repositories and their properties. For information about the architecture of SAP Mobile Documents see the Developer’s Guide. We assume that sharing is configured in the SAP Mobile Documents system. Then one of the repositories is the sharing repository. We need the following of its properties:

  • The root folder URL,
  • The ID of the user’s home folder,
  • The sharing base URL.

This information is retrieved in method ZCL_DEMO_SHARING_SERVICE->GET_REPOSITORY_INFOS (listing 3). We call this method in the constructor of ZCL_DEMO_SHARING_CLIENT after we have created an instance of IF_HTTP_CLIENT from the SM59 destination. Method GET_REPOSITORY_INFOS uses the http client to send a GET request with URL /mcm/json to the SAP Mobile Documents server. In lines 7-9, we wrap the http client object into a rest client object. In lines 10-12, we set the request URL “/mcm/json”. This is the URL to read the repository information.

In the communication with the SAP Mobile Documents server we use a CSRF token to protect against cross-site request forgery (see: Using the CSRF Token). We set the request header X-CSRF-Token=fetch in order to obtain a CSRF token from the server (lines 13-15). After the call (line 18), we get the token from the X-CSRF-Token response header (line 33). We need this token for all following requests in the same CMIS session.

Listing 3: Class ZCL_DEMO_SHARING_SERVICE, Method GET_REPOSITORY_INFOS

/wp-content/uploads/2015/01/method_get_repository_infos_629872.png

The response will be a JSON document (line 34) that contains the repository information. It has the following structure:

/wp-content/uploads/2015/01/repoinfo_json_628672.png

The keys of this JSON object are repository IDs. Each of them is mapped to an object with the properties of the repository. Among the repositories is the sharing repository. It is the unique one with the property “sharing”. We must parse the JSON to extract the data that we need for the next steps, namely the root folder URL, the home folder ID, and the sharing base URL.


How to parse the JSON response data


In lines 37-39 (listing 3), we use the ABAP statement CALL TRANSFORMATION with the XSL transformation ZDEMO_PARSE_REPOSITORY_INFOS for parsing. Generally, an XSL transformation maps XML to XML. However, CALL TRANSFORMATION allows also JSON data and ABAP data as source or target (see ABAP 2 JSON and JSON 2 ABAP with ST).  An XML representation for both, JSON and ABAP data is defined. In order to map JSON to ABAP we have to implement an XSLT or a Simple Transformation that maps the corresponding XML representations. That is what ZDEMO_PARSE_REPOSITORY_INFOS does. It maps the XML representation of the repository info JSON to the XML representation of an ABAP structure. The following picture shows the JSON data, the ABAP structure, and their XML representations.


Picture 4: Parsing the repository information

/wp-content/uploads/2015/01/repoinfo_structures_629781.png

Listings 5 shows the XSLT that transforms the XML representation of the JSON data into the XML representation of the ABAP structure.

Listing 5: XSL Transformation ZDEMO_PARSE_REPOSITORY_INFOS

/wp-content/uploads/2015/01/repoinfo_transformation_628683.png

Listing 6 shows how the transformation is invoked. We set the json string as source and the field repository_info as target.

Listing 6: CALL TRANSFORMATION Statement

/wp-content/uploads/2015/01/call_transformation_628684.png

Part 3: How to create a share from within the ABAP system

Next we create the share. On the CMIS level, a share is a folder in the sharing repository. Therefore the CREATE_SHARE method of our ABAP client sends a request to the server that executes the CMIS operation “create folder”.


The CREATE_SHARE method is similar to GET_REPOSITORY_INFOS. We wrap the http client into a rest client, set the root folder URL (a component of the repository information), and the CSRF token from the previous call (listing 7, lines 7-16).

Listing 7: Class ZCL_DEMO_SHARING_SERVICE, Method CREATE_SHARE

/wp-content/uploads/2015/01/method_create_share_629990.png

In lines 17-28 we write the body of the post request that is sent in line 30. It contains the parameters for the “create folder” CMIS operation. They are listed in the table below. Parameter “cmisaction” specifies the the operation and parameter “objectId” the parent folder of the new folder. The parent folder of a share is the home folder of the user who owns the share. This home folder ID is one of the components of the repository information which we have obtained in part 2.

The create folder operation also accepts a list of properties. We set three properties: name, description, and object type. Note that we need two parameters for each property, namely one for the property ID and another one for the property value.

Parameter Name Value
cmisaction “createFolder”
objectId The id of the parent folder of the share = home folder ID.
succinct “true”
propertyId[0] “cmis:name”
propertyValue[0] The name of the share
propertyId[1] “cmis:description”
propertyValue[1] The description of the share
propertyId[2] “cmis:objectTypeId”
propertyValue[2] “mcm:share”

The response of the create share request contains the properties of the share, in particular its object ID. Since we need the object ID for the following steps, we must parse the response. The response is a JSON with a structure as in listing 8.

Listing 8: JSON Response of the Create Share Call

/wp-content/uploads/2015/01/share_json_628685.png

Again we use CALL TRANSFORMATION with an XSL transformation for parsing (listing 7, lines 45-47). XSL Transformation ZDEMO_PARSE_CREATE_SHARE_RESP extracts the object ID of the share from the response (listing 9).


Listing 9: XSL Transformation ZDEMO_PARSE_CREATE_SHARE_RESP

/wp-content/uploads/2015/01/share_transformation_628686.png

Part 4: How to create a public link

Up to now we have created an empty share. The next step is to create a public link for the share. A share can be accessed via a public link if it has the secondary object type “mcm:publicLink”. The secondary object types of a CMIS object are stored as a multi-value property (“cmis:secondaryObjectTypeIds”) at the object. Therefore we will update this property of the shared folder. At the same time we update further properties. We do this to protect the public access of the share with a password, to define how long the public access shall be valid, and to define whether or not upload is allowed.


Method CREATE_PUBLIC_LINK of our ABAP client sends a request to the server that executes the CMIS operation “update properties”. The method is similar to the previous methods. Its code is contained in the attached file. The table below shows the parameters for the update properties operation.

Parameter Name Value
cmisaction “update”
objectId The share id
succinct “true”
propertyId[0] “mcm:enableUpload”
propertyValue[0] “true”
propertyId[1] “mcm:sharePassword”
propertyValue[1] The password
propertyId[2] “mcm:validToDate”
propertyValue[2] The timestamp of the expiration date in milliseconds since 1.1.1970, UTC
propertyId[3] “cmis:secondaryObjectTypeIds”
propertyValue[3] “mcm:publicLink”

Remark: no gaps are allowed in the sequence of indices of the property IDs and property values.


Computation of the Public Link

Method GET_PUBLIC_LINK returns the public link. The public link is the concatenation of the sharing base URL (a component of the repository information) and the share ID.

Part 5: How to upload a document

Method ZCL_DEMO_SHARING_SERVICE->CREATE_DOCUMENT uploads a document into the share. It sends a POST request with the root folder URL of the sharing repository. The content type of the request is “multipart/form-data”, and the form data are listed in the table below.

Name Value

Content-Type: text/html; charset=utf-8

Content-Length: ……

content-disposition: form-data; name=”objectid”

The share id.
More generally, if you want to put the document into
a subfolder of the share, it is the id of the parent folder.

Content-Type: text/html; charset=utf-8

Content-Length: 14

content-disposition: form-data; name=”cmisaction”

“createDocument”

Content-Type: text/html; charset=utf-8

Content-Length: 9

content-disposition: form-data; name=”propertyId[0]”

“cmis:name”

Content-Type: text/html; charset=utf-8

Content-Length: ……

content-disposition: form-data; name=”propertyValue[0]”

The document name

Content-Type: text/html; charset=utf-8

Content-Length: 17

content-disposition: form-data; name=”propertyId[1]”

“cmis:objectTypeId”

Content-Type: text/html; charset=utf-8

Content-Length: 13

content-disposition: form-data; name=”propertyValue[1]”

“cmis:document”

Content-Type: application/xml; charset=utf-8

Content-Length: ……

content-disposition: form-data; name=”……”; filename=”……”

The content of the document
To report this post you need to login first.

10 Comments

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

  1. S. Maes

    Hi Robert,

    Great article!! Thanks!

    I’ve implemented the program & classes and it works nicely in our system.

    I’m looking for a solution to expose the DMS documents within SAP ECC to SMD (for instance DMS docs attached to a service notification).

    One way is by “copying” these documents to a SMD shared folder with the notification number.

    Therfore,I’ve copied the program and classes to get the DMS doc contents and to create it in SMD. But I run into a problem when I try to create more than 1 doc in the shared folder.

    The HTTP returns with an error code 400 & the JSON error shows: “{“exception”:”invalidArgument”,”message”:”Only one content expected!”}”.

    Do you have any suggestions to correct this? That I can create multiple docs within the share?

    Also, if you’ve any suggestions to expose these DMS docs directly to SMD, they are  more than welcome!! 🙂

    Thanks in advance.

    Kind regards,

    Sander Maes

    (0) 
    1. Robert Graeff Post author

      Hi Sander,

      you are right. There is an exception when you create a second document. A refresh of the http_client object solves this issue. Please insert the following lines in method CREATE_DOCUMENT of class ZCL_DEMO_SHARING_SERVICE (at the beginning of the method directly after the DATA block):

          me->http_client->refresh_request(

             EXCEPTIONS

               http_action_failed = 1

               others             = 2

           ).

           IF sysubrc <> 0.

             RAISE EXCEPTION TYPE zcx_demo_sharing_exception

               EXPORTING

                 textid = zcx_demo_sharing_exception=>create_document_failed.

           ENDIF.


      Best regards,

      Robert

      (0) 
      1. S. Maes

        Hi Robert,

        Thanks for your quick reply!!

        And, indeed, it works! I’m now able to get the DMS docs from a Service Notification and provide them via this method (public share). Thanks! 🙂

        My next step is figuring out if I can create a SMD folder hierarchy (like the DMS Bill Of Material hierarchy) and expose the docs directly, thus without copying them first to SMD.

        If you’ve any tips on that, they are always welcome! 😉

        Kind regards,

        Sander

        (0) 
    1. S. Maes

      Hi Corneliu,

      Thanks for pointing me in the right direction.

      I’m investigating this option, it looks like the approach I need to take.

      Do you have any ABAP examples, by any change? 🙂 Or know where I can find these (already checked the other blogs & help)?

      Thanks in advance!

      Kind regards,

      Sander Maes

      (0) 
  2. Paul Fryer

    Hi all,

    Just found this document which is great.  I have this working but have hit an issue.  When I retrieve the repository info I correctly get the root URL and the root share ID.  I already have a sub-folder under this root ie the share already exists.  It is within this existing share that I want to create a new folder.

    How do I get the folder ID of this lower level folder so I can then use that to create a new folder within it ?

    Thank you for any help,

    Kind regards,

    Paul.

    (0) 
    1. Robert Graeff Post author

      Hi Paul,

      you can read a folder or document by its path. This is done by a GET request with the object URL <root folder url>/<path> and parameters:

      • name=”cmisaction” value=”object”
      • name=”succinct” value=”true”

      The response object has a property “succinctProperties”, which in turn has a property “cmis:objectId”.

      Alternatively, you can read all children of a folder. This is done by a GET request with the root folder URL and the following parameters:

      • name=”cmisaction” value=”children”
      • name=”objectId” value=<object ID of the parent folder>
      • name=”succinct” value=”true”

      To optimize the call you can also specify a filter. This can reduce the size of the response. The value of the “filter” parameter is a comma separated list of property IDs, for example “cmis:name,cmis:objectId”. The response contains then the specified set of properties.

      • name=”filter” value=<comma separated list of property IDs>.

      Best regards,
      Robert

      (0) 
  3. Muralidharan Krishnaswamy

    Hello Robert,
    Thanks for sharing useful info. We are currently implementing SAP Mobile document server. We wanted to know how does the Document Info Records and other features of traditional DMS works with SAP Mobile document servers. I read from an article that easy DMS will not be supported in S/4 1610 version. If so, does this have any impact to the existing DMS method of creating Document Info Records and object link assignments? Does Mobile doc server replaces the process of transaction CV01n? Could you pl share your knowledge and any other document that helps us in configuring the DMS config notes like Storage systems and relevant other configs? Thanks!

    (0) 
  4. EDIFICE EQUIPE PROJET

    Hello Robert,

    We have some probleme with the X-CSRF-Token eventhow the status is 200 after the HTTP request. the token is always empty.
    can ou please post the code sample bescause the link is dead.

    thank you

    (0) 

Leave a Reply