Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
16,984
This blog post, as part 1 of the BPM OData blog series, refers to the recently introduced OData Service in SAP NetWeaver BPM available with SAP NetWeaver 7.3 EHP1 SP09 and higher.

What is the BPM OData Service?

The BPM OData Service is a built-in REST service exposing selected functionalities of the BPM Public API. The service implements the Open Data Protocol (OData) and thus provides a uniform way to easily access the exposed data and functionalities. With help of this service you can easily implement a custom UI with access to BPM related data and operations. This accelerates, for example, the implementation of a custom Task Execution UI with SAPUI5, since SAPUI5 can directly connect with the service to fetch data or perform actions. This is shown in the second post of this series. The goal of this blog post is to explain the technical basics of the BPM OData Service and to demonstrate how to explore this service.

From A to Z

To demonstrate the features of the service and to give some technical insights, this blog post shows the whole round-trip for a BPM task from A to Z:

When working with tasks, you may be interested in the metadata of a task such as priority, status and deadlines. After inspecting the task’s metadata, you can go on and also have a look at the task’s input data. This contains the data given by the input mapping of the according human activity, which is used to initialize the task whose purpose is to view or edit this data. You are also able to inspect the task’s output data accordingly. You can finally complete a task by providing the values for the output data. Surely, a task can only be completed, if it is claimed before. This can also be achieved with the OData Service.

Here is an overview about the mentioned steps:
  1. Access to the metadata of a BPM task
  2. Access to the input and output data of a BPM task
  3. Claim and complete a BPM task

The following sections describe how you can execute the mentioned actions with the OData Service.

Technical Basics

Before going into details of the aforementioned actions, this section gives you a short technical background of how the BPM OData Service basically works.

The BPM OData service is a REST service that is available via a defined URL. There are different endpoints for different activities, but the basic schema yields for all operations. This schema is shown below along with one exemplary instance of this schema:

Invoking the BPM OData Service requires knowledge about the hostname and the server port used to connect to SAP NetWeaver BPM. This information is contained in the first part of the URL. During the course of this blog, this server-specific part of the URL will be skipped and a relative URL will be used instead.

The OData Service is available at root URL bpmodata followed by the specific service you want to use. For simplification, the BPM OData Service can be seen as a single OData Service, but technically the BPM OData Service is implemented as multiple services. There is one service for each type of activity. When working with tasks, there are two services available. The BPM Tasks OData Service is used to get access to the metadata of a task and to claim a task while the BPM Task Data OData Service is used to get access to the input and output data of a task and to complete a task. The details of the services are shown in the table 1.

Depending on the used service, it might be necessary to add a number of defined path segments. These path segments are specific to the used service and can differ a lot. The BPM Tasks OData Service does not require any path segments while the BPM Task Data OData Service requires task instance ID value to be specified in a path segment. The task instance ID is used in a hexadecimal format as you can find it in the SAP NetWeaver Administrator (NWA).

The last part of the URL schema is the part containing the OData resource path and some query options. This is again specific to the used service. The OData resource path specifies the resource you want to access or the operation you want to perform. This could be Claim in the BPM Tasks OData Service to claim a task or InputData in the BPM Task Data OData Service to access the input data of a task.

To ensure that only authorized users can access the BPM OData Service, it is required for a calling user to be assigned to the UME roles BPEM End User and UnifiedInboxUserRole. Furthermore, only users with the necessary permissions can execute specific actions on BPM entities, for example, only a potential owner is allowed to claim a given task.

URL Part / Service NameBPM Tasks OData ServiceBPM Task Data OData Service
Technical Service Nametasks.svctaskdata.svc
Use CaseGet metadata of a task, claim a taskGet task input and output data, complete a task
Required Path Segment(s)-Task instance ID value
Supported OData Resource Paths$metadata, TaskCollection, Claim$metadata, InputData, OutputData
Supported OData Query Options$format$expand, $format
Table 1: Details of the BPM Tasks and BPM Task Data OData Services

Running Example

This blog post series uses a simple scenario as a running example: A customer of a credit institution is getting created in the system. The example includes activities for verification of the given customer data, adding a credit limit and creation of a customer record. The process model implementing this scenario is shown in figure 1.

The task definition of the human activity for verifying the customer data uses as input data the customer data and as output data a potentially corrected version of this data. Therefore, the type of the input and output data is a complex type called Customer defined in the XML Schema Definition (XSD) shown below. The task of the second human activity for adding a credit limit uses as input data the customer data given by the previous activity and as output data the granted credit limit. The type of this credit limit is called Credit and is also defined in the XSD.
Figure 1: BPMN Process model implementing the exemplary scenario

Below is the XSD that is used to define data for the tasks of the BPM process:

  <complexType name="Customer">
    <sequence>
      <element name="firstName" type="string"></element>
      <element name="lastName" type="string"></element>
      <element name="address-street" type="string"></element>
      <element name="address-city" type="string"></element>
      <element name="address-zip" type="integer"></element>
      <element name="address-country" type="string"></element>
      <element name="currency" type="string" default="EUR"></element>
    </sequence>
  </complexType>
  <complexType name="Credit">
    <sequence>
      <element name="creditLimit" type="double"></element>  
    </sequence>
  </complexType>

In order to use the BPM OData Service with this exemplary scenario, you need to have a running BPM process instance of this process model. Starting such an instance will directly create an instance of the task that belongs to the human activity ‘Verify Customer Data’. To execute the URLs shown in this blog series, you need to have the instance ID of this task. There are several ways to start a process and to get the task instance ID; one possibility would be to start the process in the Process Repository and get the task instance ID by navigating to the Related Tasks.

Access to the Metadata of a BPM Task

Based on the technical basics described in the previous section, the following sections are now getting back to the steps needed to come from A to Z. This section starts with step A and describes how to access the metadata of a BPM task in order to inspect, for example, the priority of a task. The data referred here as metadata of a task corresponds to the TaskAbstract known from the BPM Public API.

In order to get the metadata of a task, the BPM Tasks OData Service is used along with the OData resource path TaskCollection. The Task instance ID is passed as URL parameter in parentheses and quotation marks. The OData $format query option is used to specify that the service response should be in JSON format.

The table below shows the URL used to access the metadata of a BPM task along with the service response:

HTTP MethodGET
URL.../bpmodata/tasks.svc/TaskCollection('e898ab9c36f611e3a6bf0000006379d2')?$format=json
Response Body (simplified)

{
    "d": {                    
        "TaskDefinitionName": "Verify Customer Data",
        "TaskTitle": "Verify Customer Data",
        "Priority": "MEDIUM",
        "Status": "READY",
        "CreatedOn": "/Date(1381991984453)/",    
        "LastChangedTime": "/Date(1381992249162)/",    
        "IsEscalated": false,
        "SupportsClaim": true,
        "SupportsRelease": false            
    }
}

The response of the HTTP request above contains the requested data in a key-value pair format. OData supports the possibility to describe the underlying data model, the so-called Entity Data Model (EDM). This data model is exposed with a Service Metadata Document describing entities, their properties and relations among different entities. With help of this information you can for example find out, that the priority of a task is a property of type String and the property is optional (Nullable=true). This document can be requested with the $metadata query option.

The table below shows the URL used to get the metadata of the BPM Tasks OData Service and the corresponding response:

HTTP MethodGET
URL.../bpmodata/tasks.svc/$metadata
Response Body (simplified)

<EntityType Name="Task">
    <Property Name="TaskDefinitionName" Type="Edm.String" Nullable="true"/>
    <Property Name="TaskTitle" Type="Edm.String" Nullable="true"/>
    <Property Name="Priority" Type="Edm.String" Nullable="true"/>
    <Property Name="Status" Type="Edm.String" Nullable="true"/>
    <Property Name="CreatedOn" Type="Edm.DateTime" Nullable="true"/>
    <Property Name="LastChangedTime" Type="Edm.DateTime" Nullable="true"/>
    <Property Name="SupportsClaim" Type="Edm.Boolean" Nullable="true"/>
    <Property Name="SupportsRelease" Type="Edm.Boolean" Nullable="true"/>
    <Property Name="IsEscalated" Type="Edm.Boolean" Nullable="true"/>
</EntityType>

Access to the Input and Output Data of a BPM Task

The input data of a task contains the data used to initialize the task while the output data contains the result of the completed task.

Input Data

Accessing the input data returns a data object called InputData which contains the data as specified with the input data mapping of the human activity within the process model. In the running example it is an entity called Customer containing the data set of a customer with the first name John and the last name Doe.

In order to get the Input Data of a Task, the BPM Task Data OData Service is used along with the OData resource path InputData. The Task instance ID is passed as URL path segment and as URL parameter. It is also possible not to pass the task instance ID as parameter, but this will change the format of the response. Instead of returning the Input Data as a single entity, an Atom feed is returned which contains the Input Data as single element.

The OData $expand query option is used to specify that referenced entities should be represented inline within the service response. The name of the entities to expand is passed with the option. In the example below the referenced entity Customer is getting expanded and therefore represented inline in the response. Omitting the expand option would result in a service response containing only the wrapper element InputData without any further data.

The table below shows the URL used to access the input data of a BPM task along with the service response:

HTTP MethodGET
URL.../bpmodata/taskdata.svc/e898ab9c36f611e3a6bf0000006379d2/InputData(' e898ab9c36f611e3a6bf0000006379d2')?$expand=Customer&$format=json
Response Body

{
    "d": {
        "Customer": {
            "firstName": "John",
            "lastName": "Doe",
            "address-street": "Main str.",
            "address-city": "Springfield",
            "address-zip": 19064,
            "address-country": "USA",
            "currency": "USD"
        }
    }
}

Like the BPM Tasks OData Service, the BPM Task Data OData Service also supports requesting the Service Metadata Document, but specific for each particular task instance ID. This document describes the structure of the input data as well as the structure of the output data. The returned EDM is generated automatically from the XSD defining the data types used by the BPM task and thus provides the information about name, type and default value of the single properties.

In the example below, the task Verify Customer Data is used. The input and output data of this task have the same data type, i.e. Customer. This is also reflected in the resulting EDM. In case of a different XSD structure for input and output data, EDM structure would differ as well.

The table below shows the URL used to get the metadata of the BPM Task Data OData Service and the corresponding response:

HTTP MethodGET
URL.../bpmodata/taskdata.svc/e898ab9c36f611e3a6bf0000006379d2/$metadata

Response Body

(simplified)


<EntityType Name="InputData">
    <NavigationProperty Name="Customer"
      Relationship="BPMTaskData.InputData_Customer"
      FromRole="InputData" ToRole="Customer"/>
</EntityType>
<EntityType Name="OutputData">
    <NavigationProperty Name="Customer"
     Relationship="BPMTaskData.OutputData_Customer"
      FromRole="OutputData" ToRole="Customer"/>
</EntityType>
<EntityType Name="Customer">
  <Property Name="firstName" Type="Edm.String" Nullable="true"/>
  <Property Name="lastName" Type="Edm.String" Nullable="true"/>
  <Property Name="address-street" Type="Edm.String" Nullable="true"/>
  <Property Name="address-city" Type="Edm.String" Nullable="true"/>
  <Property Name="address-zip" Type="Edm.Decimal" Nullable="true"
      DefaultValue="0"/>
  <Property Name="address-country" Type="Edm.String" Nullable="true"/>
  <Property Name="currency" Type="Edm.String" Nullable="true"
      DefaultValue="EUR"/>
</EntityType>

Output Data

The service request to get the task output data is almost the same as the one to get the input data except of the OData entity set name that is OutputData in this case. Requesting the output data of an open task will return an empty data object, since the output data of a task is only set when completing the task.

The table below shows the URL used to access the output data of a BPM task along with the service response:

HTTP MethodGET
URL.../bpmodata/taskdata.svc/e898ab9c36f611e3a6bf0000006379d2/OutputData(' e898ab9c36f611e3a6bf0000006379d2')?$expand=Customer&$format=json
Response Body

{
    "d": {    
        "Customer": {      
            "firstName": null,
            "lastName": null,
            "address-street": null,
            "address-city": null,
            "address-zip": null,
            "address-country": null,
            "currency": null
        }
    }
}

Claim and Complete a BPM Task

In SAP NetWeaver BPM, you must claim a task before you will be able to complete it. This can be done with help of the BPM Tasks OData Service using the OData resource path Claim. The task instance ID of the respective task is passed with the query option InstanceID.

In contrast to the requests mentioned before (for example, getting the input data of a task), this activity is not about getting some data from the OData Service but about executing a particular action, i.e. claiming a task. Thus, an HTTP POST request is used to trigger the action instead of an HTTP GET request, which is usually used to request some data. A POST request includes some headers and a body containing some data. The headers are explained later along with a description of how you could actually execute a POST request.

The table below shows the URL used to claim a BPM task:

HTTP MethodPOST
URL.../bpmodata/tasks.svc/Claim?InstanceID='e898ab9c36f611e3a6bf0000006379d2'
Request HeadersAuthorizationBasic dXNlcm5hbWU6cGFzc3dvcmQ=
X-CSRF-Token781057a9-b96a-468c-b393-981f98292335
Request Body<empty>
Response BodyOData entry representing the claimed BPM Task

Once the task is claimed, you will be able to complete it. For that purpose, you send an HTTP POST request to the URL similar to the one that is used to get the task output data. The request body contains the output data that will be used to complete the task. In case of the running example, a modified version of the input data is used to complete the task. This is possible because the task uses the same data type for input and output data. If the data types for input and output data are different, the output data needs to be created based on the described structure in the EDM.

The table below shows the URL used to complete a BPM task along with the service response:

HTTP MethodPOST
URL.../bpmodata/taskdata.svc/e898ab9c36f611e3a6bf0000006379d2/OutputData
Request HeadersAuthorizationBasic dXNlcm5hbWU6cGFzc3dvcmQ=
X-CSRF-Token781057a9-b96a-468c-b393-981f98292335
Acceptapplication/json
Content-Typeapplication/json
Request Body

{
    "Customer": {
        "firstName": "Max",
        "lastName": "Mustermann",
        "address-street": "Haupt Str.",
        "address-city": "Walldorf",
        "address-zip": 69190,
        "address-country": "Germany"
    }
}
Response Body

{
    "d": {
        "Customer": {
            "firstName": "Max",
            "lastName": "Mustermann",
            "address-street": "Haupt Str.",
            "address-city": "Walldorf",
            "address-zip": 69190,
            "address-country": "Germany",
            "currency": "EUR"
        }
    }
}

Attentive readers probably noticed that the currency property has not been specified in the POST request body, but it is set to EUR in the service response. In case the value for a required property is not provided in the POST request body (currency is a required element having defined a default value in the XSD definition), the service will use its default value to complete the task.

How to Send a POST Request?

As it was mentioned before, HTTP POST requests are used to claim and complete a BPM task. For performing a POST request a regular web browser cannot be used. To perform a POST request you need to use a REST client. For this purpose, we will use Postman. It is a REST client distributed as an add-on for Google Chrome browser. In case you want to use your own REST client instead of Postman, please make sure that the client supports the reuse of the same HTTP session across different HTTP requests. Otherwise, you might face with problems during claiming or completing a BPM task.

The screenshot below shows how to send a POST request to complete a BPM task with Postman:

What Do all These HTTP Headers Mean?

As some of you probably noticed there are some HTTP headers specified for the POST requests to claim and complete the task. Content-Type and Accept are standard HTTP headers used to specify media type for the request and response bodey respectively. Authorization header is used to specify user credentials for authentication. In the example, this header has a Base64-encoded value generated by Postman. To generate this value in Postman go to the Basic Auth tab of the Postman UI, enter user credentials and click the Refresh headers button.

A POST request can be considered as a write operation. It means that additional security considerations should be taken into account to secure BPM process data. The BPM OData services are implemented to prevent CSRF attacks in case write operation is performed. This is implemented with the HTTP header X-CSRF-Token, which is used to send CSRF tokens in both directions. As it was mentioned before, this header is checked only for write operations, i.e. only for POST requests. The CSRF token is generated by the service, which means that before you specify the header value for a POST request you need to get it from the service. For that purpose, you can send any valid GET request to the service adding X-CSRF-Token HTTP header with the value Fetch. After receiving the generated value from the service, you can use this value in the HTTP header of your POST request to complete a task. The generated value is valid only within the same HTTP session.

The figure below shows the URL used to request the generation of the value for the X-CSRF-Token header along with the response containing the generated value:

Restrictions

Providing access to a task’s input and output data requires knowledge of the used data types. In BPM these data types are defined with an XML Schema Definition (XSD). This XSD is translated by the BPM OData Service in an OData conform representation of the data structure, i.e. EDM. As of SAP NetWeaver 7.3 EHP1 SP09, this translation only supports a complex type acting as a wrapper, which contains some primitive types. See also the running example, which uses a complex type Customer with primitive types describing the name and the city of the customer.

In case your wrapper element does not only contain primitive types but also complex types, you can bypass this restriction by unwinding the embedded complex types to own simple properties with the name of the complex data type as prefix. This workaround is shown below:

Complex type unwound to simple properties:


<complexType name="Customer">
    <sequence>
        <element name="firstName" type="string"></element>
        <element name="lastName" type="string"></element>
        <element name="address-street" type="string"></element>
        <element name="address-city" type="string"></element>
        <element name="address-zip" type="integer"></element>
        <element name="address-country" type="string"></element>
        <element name="currency" type="string" default="EUR"></element>
    </sequence>
</complexType>

Use of embedded complex type:


<complexType name="Customer">
    <sequence>
        <element name="firstName" type="string"></element>
        <element name="lastName" type="string"></element>
        <element name="address" type="Address"></element>    
        <element name="currency" type="string" default="EUR"></element>
    </sequence>
</complexType>
<complexType name="Address">
    <sequence>
        <element name="street" type="string"></element>
        <element name="city" type="string"></element>
        <element name="zip" type="integer"></element>
        <element name="country" type="string"></element> 
    </sequence>
</complexType>

More information about the restrictions of the BPM OData Service as of SAP NetWeaver 7.3 EHP1 SP09 you can find in the BPM OData Services documentation.

Error Handling

Sometimes bad things happen. In case something goes wrong during the service request processing, you will get a service response containing a log ID along with a corresponding HTTP status code, e.g. HTTP 500 (Internal Server Error) or HTTP 404 (Not Found). You can inspect the log entry identified with the given log ID by using the SAP NetWeaver Log Viewer. The technical information about the error including the exception stack trace is located in SAP NetWeaver Developer Traces.

Conclusion

This part has shown the whole round-trip for a BPM task; the metadata and the input data of a task can be retrieved, a task can be claimed for a given user, and the output data can be sent to complete a task. In the next part we will show how this round-trip of operations can be used to implement a Task Execution UI based on SAPUI5.

25 Comments