Skip to Content
Author's profile photo Sven Huberti

SAP API Management – SOAP Service as REST API

Introduction

In this tutorial, I will explain how to expose a SOAP WebService as a REST API.

The prerequisite for this tutorial, is that you are acquainted with SAP API Management, eg. that you have already created some API proxies like described in Holger Bruchelt’s document How to use SAP API Management on HCP Trial

This proxy can be created on the SAP API Management Trial environment.

For the purpose of the tutorial, I will use a public web service called “Calculator” that is availablehere. This WebService allows to execute mathematical operations. In our case, we will hardcode the “add” operation.

If you are interested in getting a working proxy, that you can import into your environment, feel free to reach out to me.

Overview

First of all, note that with an API Proxy, you can access a web service either by setting up the backend to be the target of your proxy, or by making a so called “Callout” from within the proxy. In our tutorial, we will use the WebService as target backend.

Before we get our hands dirty, let’s see what our master plan is. The diagram below is a view of what we’ll do in this tutorial:

1- Create the API proxy: we will create a proxy that will expose the “Calculator” WebService as a REST API, that can be reached over “<SAP HCP APIM URL>/v1/calculator”, using the calculator web service as target backend.

API Proxy Request flow:

2- Generate the SOAP request: SOAP WebServices requires specifically formatted requests. The REST API we’ll provide is easier to use, and only requires 2 query parameters. To map these parameters to the specific SOAP WS request, we will generate the request using an “Assign Message” policy.

Response:

The web service response is an XML response, with a lot of metadata, that is not always useful to the REST API consumer. JSON has proven to be an ideal notation for apps or web applications, being lightweight, simple to understand and to use. For these reasons, we will convert the XML response into JSON, and remove the metadata, so that the REST API is easy to use and lightweight.

To achieve this we will:

3- Convert the response to JSON: with a “XML t oJSON” policy, the XML response will be converted to JSON,

4- Beautify the response: with an “Extract Variables” policy, we will extract the desired information from the JSON, add set it as the API proxy response.

1- Create the API Proxy

Log into your Hana Cloud Cockpit, and navigate to the “API Management” Service.

In the APIM Dashboard, select “Quick Actions” > “Create Artifacts” > “API”:

In the API Proxy creation window, enter the details as follows:

API Provider: None

URL: http://ws1.parasoft.com/glue/calculator

Name: Calculator

Title: Calculator

Description: This API will execute mathematical operations

API base path: /v1/calculator (it is a best practice to always add a version to the base path of your API)

Service Type: REST

Hit the “Create” button, and then “Save and deploy”.

2- Generate the SOAP request

When calling our REST API, we will use 2 parameters, Number1 and Number2. These will be the number used for the addition the service will make, for instance:

The response of /v1/calculator?Number1=10&Number2=30 will be 40

In order to place a SOAP call, we need to generate a SOAP request. This SOAP request has a specific structure, with specific headers and XML payload, containing the request parameters.

To do so, open the Policy Designer by clicking on “Policies” from within your API.

Click on the “Edit” link on the right-bottom corner.

Click on the “ProxyEndpoint>PreFlow” on the left “Flow” panel.

Click on the “+” sign of the “Assign Message” policy, on the right-handed “Policies” panel.

Name: GenerateSOAPRequest

EndpointType and FlowType were set for you when you clicked on the “ProxyEndpoint>PreFlow” link in the previous step

Stream: Incoming Request

Click on “Add” to add the policy to the flow.

The “Assign Message” policy is very powerful, and lets you assign values to headers, query parameters, payload, custom variables, etc.. In our case, we will use it to define the required SOAP call, dynamically created using our query parameters.

Replace the XML configuration of your Assign Message policy with the following:

  1. <AssignMessage async="false" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'>
        <Set>
            <Headers>
                <Header name="SOAPAction">add</Header>
                <Header name="Content-Type">text/xml; charset=utf-8</Header>
            </Headers>
            <Payload contentType="text/xml">
                <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                    <soap:Body>
                        <add xmlns="http://www.parasoft.com/wsdl/calculator/">
                            <!--Required-->
                            <x>{request.queryparam.Number1}</x>
                            <!--Required-->
                            <y>{request.queryparam.Number2}</y>
                        </add>
                    </soap:Body>
                </soap:Envelope>
            </Payload>
            <Verb>POST</Verb>
        </Set>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
        <AssignTo createNew="false" transport="http" type="request"/>
    </AssignMessage>

Note that the AssignMessage policy will:

– create 2 headers,

– create the XML payload as required by the web service,

– set the “Verb” to POST since all SOAP transactions are “POST”.

This configuration is then assigned to the request that will go to the backend, ie. the Calculator web service.

Also note that we are dynamically setting the parameters “x” and “y” that are required by the web service endpoint, using a specific notation: the curly brackets mean that we reference the value a flow variable: “{<var_name>}“. This flow variable is either user-defined, and set by using an “Assign Message” policy, or pre-defined, and set during runtime.
In our case, we use a pre-defined variable called “request.queryparam” and append the name of the query parameter we want to retrieve. At runtime, “{request.queryparam.Number1}” will be replaced by the value of the query parameter “Number1”.

Click on the “Update” link at the right-bottom corner of the PolicyDesigner.

Click on the “Save” link at the right-bottom corner of the API Proxy overview.

It’s a good idea to test the proxy now. To do so, simply open a browser window (preferably Chrome) and paste the URL of your proxy. Add the parameters “Number1” and “Number2” to your request and run the query.

As you can see, the request is passed to the SOAP backend, which returns the XML data according to your query parameters.

However, as an app developer, I would love to have that information in a lightweight and simple-to-use format: JSON. Therefore we will convert and beautify the response.

3-Convert the response to JSON

Converting XML data to JSON is very simple with SAP API Management. You only need to add a “XML to JSON” policy on the response flow of your proxy.

To do so, open the Policy Designer by clicking on “Policies” from within your API.

Click on the “Edit” link on the right-bottom corner.

Click on the “ProxyEndpoint>PreFlow” on the left “Flow” panel.

Click on the “+” sign of the “XML to JSON” policy, on the right-handed “Policies” panel (you may need to scroll down to see the policy).

Name: XMLtoJSON

EndpointType and FlowType were set for you when you clicked on the “ProxyEndpoint>PreFlow” link in the previous step

Stream: Outgoing Response

Click on “Add” to add the policy to the flow.

The “XML to JSON” policy can be configured in several ways to fit your needs. In our case, we simply specify that the text for an empty node name is “value”.

Use the following configuration for your policy:

  1. <!-- This policy converts an XML payload to JSON structure -->
    <XMLToJSON async="false" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'>
      <Options>
        <TextNodeName>value</TextNodeName>
      </Options>
      <!-- The variable to which the converted JSON should be assigned to -->
      <OutputVariable>response</OutputVariable>
      <!-- The variable that we want to convert to JSON -->
      <Source>response</Source>
    </XMLToJSON>

Click on the “Update” link at the right-bottom corner of the PolicyDesigner.

Click on the “Save” link at the right-bottom corner of the API Proxy overview.

Test your proxy again using the previous URL.

The response of the proxy now looks much simpler and easier to consume:

4- Beautify the response

Even though the response is now lightweight and easy to use, let’s improve it even more (this is not a necessity, but a good excuse to have a look at another policy!).

Just as there is XPath for XML, there is JSONPath for JSON. SAP API Management provides an “Extract Variables” policy that can execute a JSON path expression against JSON payload.

Our current response payload looks like this:

  1. {
      "Envelope":{
          "Body":{
            "addResponse":{ 
                "Result":{ 
                  "type":"xsd:float",
                  "value":"35.0"
                }
            }
          }
      }
    }

What we would like to end up with, is only the “addResponse” code:

  1. { 
        "Result":{ 
              "type":"xsd:float",
              "value":"35.0"
        }
    }

We will use the following JSONPath expression: “$.Envelope.Body.addResponse” that points at the “addResponse” element of our payload, starting from the root (“$”).

To do so, open the Policy Designer by clicking on “Policies” from within your API.

Click on the “Edit” link on the right-bottom corner.

Click on the “ProxyEndpoint>PreFlow” on the left “Flow” panel.

Click on the “+” sign of the “Extract Variables” policy, on the right-handed “Policies” panel (you may need to scroll down to see the policy).

Name: GetResponseOnly

EndpointType and FlowType were set for you when you clicked on the “ProxyEndpoint>PreFlow” link in the previous step

Stream: Outgoing Response

Click on “Add” to add the policy to the flow.

Use the following code the configures the execution the above JSONPath:

  1. <ExtractVariables async="true" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
        <JSONPayload>
            <Variable name="response.content">
                <JSONPath>$.Envelope.Body.addResponse</JSONPath>
            </Variable>
        </JSONPayload>
        <Source>response</Source>
    </ExtractVariables>

The policy above executes the JSONPath against the source “response”, and sets the value of the result into the variable “response.content“. This variable is a predefined variable, and contains the response of the API proxy. We are actually overwriting the response, with the result of the JSONPath expression with our policy.

Click on the “Update” link at the right-bottom corner of the PolicyDesigner.

Click on the “Save” link at the right-bottom corner of the API Proxy overview.

Test your proxy again using the previous URL.

Final words

As you may have seen throughout this tutorial, SAP API Management provides the ability to quickly and simply adapt a web service to expose it as REST API, and adapt it to your specific needs. I hope that even if we only have scratched the surface, you got an idea of what is possible, and that you’ll have fun in the future using HCP SAP APIM!

For any questions or comment feel free to contact me or to leave a comment below.

Assigned Tags

      5 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      herbal sejagat Obat Herbal Penyakit Jantung Bocor yang dapat dipercaya & sangat manjur dalam membantu tahap memulihkan penyakit jantung bocor pada anak anda.  obat herbal jantung bocor alami ampuh

      Author's profile photo JOnes Peter
      JOnes Peter

      Fantastic blog and has helped hugely with me in proving connectivity between a trial account for API Management and our on-premise PI platform. One thing I seem to have an issue with is that when I create my API Proxy as a SOAP service (rather than REST as in your example) that the API Test Console doesn't appear top work! Basically I get no response body or header

       

       

      I spent several days trying to understand what was wrong and only after triggering the same request using SOAPUI did I realise that the service is working:

       

       

       

      Any ideas why this is the case?

      Author's profile photo Sven Huberti
      Sven Huberti
      Blog Post Author

      Hello Peter,

      sorry: I can't help you on this.

      API Management really is about REST APIs, less about SOAP WebServices, hence I never really worked with SOAP-to-SOAP scenarios over API Management...

      FYI: all the tests (debug and test) I did based on the SOAP-to-REST scenario I describe above did work successfully... I just tested them again, in case something changed in the SOAP WS implementation.

      BR,
      Sven

      Author's profile photo JOnes Peter
      JOnes Peter

      Thanks Sven for responding but I agree with you that your 'SOAP-to-REST' all work but this is a case where you are taking a back-end SOAP service and exposing it as a REST service. I could go with this approach but for my understanding and knowledge I wanted to do a SOAP-to-SOAP scenario and this is where the test console doesn't appear to work!

      Author's profile photo j soler
      j soler

      Great blog Sven Huberti, thanks!

      I have some doubts about the mapping/transformation capabilities of SAP APIM.

      For security reasons, we need to make an intermediate call to validate a SAP CDC JWT token, no problem here. The thing is that we also need to extract a value from the token (the CDC uid) and map it to a field in the SOAP webservice. Would this be possible? I don't have a development environment yet, so I've been checking blogs and although I've found functionalities to transform the message, I'm not sure if something as concrete as mapping a single field without altering the rest of the request is possible.

      By the way, the target is a SOAP webservice of SAP CRM (on premise), I assume that's not a problem.

      Thanks and kind regards,
      Judit