SOAP to REST Transformation

Author: Rizwan, Mohammed

Supported Versions: 10.0 & above

Introduction

This tutorial will help the users to understand the functionality of SOAP-to-REST transformation and how to use it in API Gateway.

Feature Description


SOAP web services are commonly used to expose data within enterprises. With the rapid adoption of the REST APIs, it is now a necessity for API providers to have the ability to provide RESTful interfaces to their existing SOAP web services instead of creating new REST APIs. Using the API Gateway SOAP to REST transformation feature, the API provider can either expose the parts of the SOAP API or expose the complete SOAP API with RESTful interface. API Gateway allows you to customize the way the SOAP operations are exposed as REST resources. Additionally, the Swagger or RAML definitions can be generated for these REST interfaces.

Requirement


API Provider wants to expose all or some of the operations from the existing SOAP service as a REST service instead of creating new REST APIs.

Prerequisites

SOAP API should be created in the API Gateway.

Capabilities

  • API Gateway allows to enable SOAP API in a RESTful way to its clients and disabled it by default.
  • The API Provider can enable all or some operations of an SOAP API to be exposed as REST to the users.
  • After enabling, the SOAP Operation is ready to be invoked in a RESTful way with default values.
  • The API Provider can configure custom values for the resource paths and the methods.
  • The API Provider can also modify the default request/response schemas and examples that are generated.
  • API Gateway handles the SOAP API attachments by using multipart/form-data or multipart/mixed content-types

Below screenshot shows the sample soap operation and its equivalent REST resource.

Steps to enable REST transformation

  • Go to API details page
  • Edit the API
  • Click 'Rest transformation'
  • Use the toggle button next to 'Transform all operations' to transforming all the operations.
  • Use the toggle button next to each operation to transform the specific operation.

Default values



API Gateway allows the API Provider to select the operations from the created SOAP API to transform it to REST resources. REST resource is created with the below attributes.
 

Artribute Name Description
Resource Name Name of the operation
Resource Path /{Name of the operation}
HTTP Method POST
Example of the input request for content-type application/json and application/xml Json and xml sample are derived from the input message of the operation
Example of the output response for content-type application/json and application/xml Json and xml sample are derived from the output message of the operation


Below is the screenshot of the UI to show the default value when enabling the operation to expose it as a REST resource
 

API Gateway also provides the flexibility to modify the REST resource attribute values. API Provider can modify the resource name, resource path, method, sample for request and response. He can also add a new parameter, content-type based request, response and content-type based schema and sample under the response.

API Gateway provides way to transforming all the operations in a single toggle button or transform selective operations.

Employee Service



Let's take employee service as an example to understand this feature better. Link to the input file EmployeeService.wsdl used for creating this SOAP API. Employee service has 5 soap operations to support CRUD operations. Let's transform all the operations into a proper REST service by adding/modifying the attributes like method, parameters, etc. The below table contains existing SOAP operations with their equivalent REST resource, method and parameter type.

SOAP Operation REST Resource Method Parameter
createEmp /employee POST Body parameter
updateEmp /employee/{id} PUT Body, query parameter
deleteEmp /employee/{id} DELETE Query parameter
getEmp /employee/{id} GET Query parameter
getAllEmployees /employee GET NA

Use case 1 - Create employee

Expand the createEmp soap operation and change the resource path as '/employee'. No change is required for 'method' as it is POST by default.

Use case 2 - List all employees

Expand the getAllEmployees soap operation and change the resource path as '/employees', method as GET. As GET operation does not require the input request, both the content-type-based body parameter was removed.

Use case 3 - Read employee

Expand the getEmp soap operation and change the resource path as '/employee/{id}', method as GET. As GET operation does not require the input request, both the content-type based body parameter were removed. New path parameter 'id' is added where the type is a string, required is true and XPath is //employeeId.

Path parameters in a resource path and query parameters in the request need to be mapped to the SOAP element in request to be sent to the Native service using Xpaths.

Setting the xpath is to link the employeeId in the REST resource with the employeeId field in the input request of the getEmp. Below is the sample input request of getEmp.

Use case 4 - Update employee

Expand the updateEmp soap operation and change the resource path as '/employee/{id}', method as PUT. New path parameter 'id' is added where the type is a string, required is true and xpath is //employeeId

Use case 5 - Delete employee


Expand the deleteEmp soap operation and change the resource path as '/employee/{id}', method as DELETE. As the DELETE operation does not require the input request, both the content-type based body parameter was removed. New path parameter 'id' is added where the type is a string, required is true and xpath is //employeeId.

REST Resource Runtime Invocation



A SOAP API that is exposed in API Gateway would usually mediate the SOAP request that the clients send to the Native API. When the provider wants to expose the same SOAP API for Mobile applications sending JSON requests, API Gateway takes the responsibility to convert this RESTful request into SOAP form such that this request can be forwarded to the Native SOAP API.

Below table shows the request and response of the generated REST resources

 

Operation Request Response
Create employee POST /ws/EmployeeService/1/employee HTTP/1.1
Host: MCMRIZ01:5555
Content-Type: application/json
Accept: application/json
Authorization: Basic QWRtaW5pc3RyYXRvcjptYW5hZ2U=
Cache-Control: no-cache
Postman-Token: 0a69f487-6cac-c23e-8c48-7b60c1d6046d
{
"employeeName": "Yuvraj Singh",
"employeeDesignation": "Cricketer",
"employeeSalary": "100000",
"managerId": "12345",
"department": "54321"
}
{
  "createEmpResponse": {
    "result""Emplyee added successfully"
  }
}
List all employees GET /ws/EmployeeService/1/employee HTTP/1.1
Host: MCMRIZ01:5555
Accept: application/json
Authorization: Basic QWRtaW5pc3RyYXRvcjptYW5hZ2U=
Cache-Control: no-cache
Postman-Token: 190b7a31-f3eb-e0f7-2264-7b85b29e643a
{
  "getAllEmployeeResponse": {
    "result": {
      "@nil""true"
    },
    "employee": [
      {
        "empId": 21,
        "empName""Yuvraj Singh",
        "designation""Cricketer",
        "salary": 100000,
        "mgrId": 12345,
        "department": 54321,
        "profilePic""",
        "profileDoc"""
      },
      {
        "empId": 30,
        "empName""Smith",
        "designation""Dev",
        "salary": 20000,
        "mgrId": 7000345,
        "department": 1,
        "profilePic""",
        "profileDoc"""
      }
    ]
  }
}
Read employee GET /ws/EmployeeService/1/employee/21 HTTP/1.1
Host: MCMRIZ01:5555
Accept: application/json
Authorization: Basic QWRtaW5pc3RyYXRvcjptYW5hZ2U=
Cache-Control: no-cache
Postman-Token: 455a9453-daa2-a809-dcdb-4157e30c9956
{
  "getEmpResponse": {
    "result": {
      "@nil""true"
    },
    "employee": {
      "empId"21,
      "empName""Yuvraj Singh",
      "designation""Cricketer",
      "salary"100000,
      "mgrId"12345,
      "department"54321,
      "profilePic""",
      "profileDoc"""
    }
  }
}
Update employee PUT /ws/EmployeeService/1/employee/21 HTTP/1.1
Host: MCMRIZ01:5555
Accept: application/json
Authorization: Basic QWRtaW5pc3RyYXRvcjptYW5hZ2U=
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 0b5f008a-2247-35a6-dc04-e35552e403fa
{
"employeeName": "Yuvraj Singh",
"employeeDesignation": "Cricketer Updated",
"employeeSalary": "100000",
"managerId": "12345",
"department": "54321",
"employeeId" : "21"
}
{
  "updateEmpResponse": {
    "result""Employee updated successfully"
  }
}
Delete employee DELETE /ws/EmployeeService/1/employee/21 HTTP/1.1
Host: MCMRIZ01:5555
Accept: application/json
Authorization: Basic QWRtaW5pc3RyYXRvcjptYW5hZ2U=
Cache-Control: no-cache
Postman-Token: e6f5d9a6-5e8f-6aff-042f-b5125692e899
{
  "deleteEmpResponse": {
    "result""Emplyee deleted successfully"
  }
}

Exported into standard formats

API Gateway allows the REST definition of the SOAP API to  be exported as a Swagger/RAML files for the external clients. Find the swagger file as EmployeeService.json and raml file as EmployeeService.raml in the specifications section in the API details page.



Link to the exported swagger EmployeeService.json, raml EmployeeService.raml, exported archive apiarchive.zip as a reference.

image.png

image.png

apiarchive.zip (4.82 KB)

EmployeeService.json (6.08 KB)

EmployeeService.raml (5.44 KB)

Further read:
Get to know the various ways in which you can consume and expose REST APIs in webMethods Integration Server: REST Capabilities In Integration Server

This is an interesting feature, but beware of its limitations. The main limit one is likely to encounter is that it impossible, without some sort of help, for the XML to JSON translation to know when a single element is a singleton of an array. Thus, if the XML has 2+ elements, the resulting JSON will have an array. But with just 1 element, it will not. Resulting in interpretation challenges.

This was changed in 10.11. Now, API Gateway allows for configuring what should happen is such cases: (i) convert XML to JSON based on the XML response from the backend (i.e. show single element or array depending on the answer) or (ii) conform to the schema (e.g. convert as an array even if the baked served a single element).

1 Like

Right – which means the transformation gets “some sort of help.” In this case, a separate definition of the target document. The limitation still exists, it is just that API GW now explicitly provides (another) way to provide that help.

1 Like

Should note too that this is effectively never a good approach to adopt. This will cause problems for unsuspecting clients – “sometimes it works, sometimes it fails”.

While API GW supports doing it this way, IMO this way should never be implemented. Should always augment the transform with a target document type. Or use underlying IS capabilities to parse the XML (which API GW presumably does as well) to an IS document, with appropriate doctype and makeArrays settings to get the right structure cardinality for all elements, then create the JSON string from the IS doc.

Don’t forget about element attributes and namespace prefixes. Those will likely need specific attention too.

If the XML is basic and is known for certain that none of the items will ever be present (no arrays, no attributes, no namespace prefixes) then the basic transform may be okay.

Hopefully this info is helpful.

@reamon @Przemek_Kulik1 Is there any way to handle element name conflicts. Because i have elements with same name and different namespaces in the soap. These elements are under different parent elements (In JSON under different objects) . But when i use the rest transformation option and convert from JSON to SOAP, it is not referring to the right name space .

How is the JSON carrying the namespace info, if at all? There are schemes used by tools like json.net that put the namespace declarations in JSON fields. API GW might support that somehow but I’ve never investigated that.

IMO, don’t use the API GW generic transformation in this case. Use IS and its capabilities instead. You can try to create something generic that could handle arbitrary structures, namespaces (including default namespaces), etc. Or implement document definition-specific steps that explicitly map a specific JSON definition to a specific XML definition and vice versa. E.g. 2 doc types, one for the structure that matches the JSON definition (names, arrays, nested structures, etc) and one for the structure that matches the XML defintion (names, namespaces, namespace prefixes, etc.) with mapping between them accounting for the namespaces in some way.