SOAP, however, has not been the de facto approach for
building modern Web application for some time now. With the creation of new protocols and
standards, REST (Representational State Transfer) and JSON (JavaScript Object
Notation) are now widely used for new projects, leaving SOAP services mostly on
maintenance or support mode only.
SOAP began to lose momentum because of its limitations. The XML
message format is a verbose compared to the JSON format. SOAP is also tightly
coupled as the client-server communication uses a strict contract definition,
WSDL (Web Service Description Language). RESTful APIs in contrast provide an
architectural style with loose guidelines and supports several message formats
like plain text, XML, JSON, HTML.
Replacing a SOAP Service
The decision to replace a SOAP service with other
technologies can be a challenging one. Depending on how complex the project is,
it may just be a tremendous investment full of risks for any company. In
addition, there are the operation cost to support the new technology and still
support clients that cannot migrate to the new API definition.
Some companies may also have the argument that their APIs
are doing a great job, and they do not need to be updated with new technology. For some clients, however, it may be a risk to
take on an integration investment with a company that supports, what many
perceive as, older technology, or that there are security limitations. Luckily
for situations like this, there are alternatives that can meet both sides of
the argument.
Modernize
a SOAP API
With the growth of cloud technology, there are ways to
modernize a legacy API without having to re-write the API which immediately
becomes very appealing as this effort saves companies with project management and
implementation cost. For a solution like
this, we need a system that can provide a reverse-proxy and document format
mapping capabilities. Azure cloud
provides the perfect solution with the API Management service offering.
API Management (APIM) Service
Azure APIM service accelerates this kind of solutions by
providing multiple capabilities which enables the managing of APIs by
protecting the resources with authentication, authorization, IP Whitelisting,
and usage limits. It also provides reverse-proxy capabilities which enable
companies to publish REST-based APIs by creating Open API endpoints which act
as façade for the legacy systems. It supports the transformation of XML
documents into JSON documents and Vice-Versa which makes it the obvious
solution for modernizing a legacy SOAP API.
Modernization Process
The process to modernize a legacy SOAP API is much simpler
and takes lot of less effort than to take on a rewriting effort. This is mostly
due to the metadata reading capabilities of the APIM service. The process starts
by importing a WSDL document into the service which reads the metadata to create
facades with mapping policies for inbound and outbound stages of the request
lifecycle. The façade is the Open API
definition of the RESTful service. The mapping policies enable the mapping and
transformation of JSON to XML documents for inbound processing as well as XML
to JSON transformation for outbound processing. The Inbound stage handles the
JSON payload request which needs to be transformed into XML, so it can be
proxied to the legacy SOAP API. The
outbound stage handles the XML response from the legacy SOAP service, and it
transforms the response into a JSON document, so the client application can
consume it.
Sample Process
Now that there is a good conceptual understanding of the
approach, let’s look at a practical example by using a publicly available SOAP
API which returns a list of continents by name. Note that any other SOAP API can be used
instead as the process is really the same. Let’s review the SOAP API
specifications for this Web service.
Service endpoint:
http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso
Open or use any tool like Postman
that can enable sending API requests to the service. Send a POST request with
this header Content-Type: text/xml. Also
add the following for the request body payload.
<?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <ListOfContinentsByName xmlns="http://www.oorsprong.org/websamples.countryinfo"> </ListOfContinentsByName> </soap12:Body> </soap12:Envelope>
|
The expected response should be an
XML document that looks as follows:
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <m:ListOfContinentsByNameResponse xmlns:m="http://www.oorsprong.org/websamples.countryinfo"> <m:ListOfContinentsByNameResult> <m:tContinent> <m:sCode>AF</m:sCode> <m:sName>Africa</m:sName> </m:tContinent> <m:tContinent> <m:sCode>AN</m:sCode> <m:sName>Antarctica</m:sName> </m:tContinent> <m:tContinent> <m:sCode>AS</m:sCode> <m:sName>Asia</m:sName> </m:tContinent> <m:tContinent> <m:sCode>EU</m:sCode> <m:sName>Europe</m:sName> </m:tContinent> <m:tContinent> <m:sCode>OC</m:sCode> <m:sName>Ocenania</m:sName> </m:tContinent> <m:tContinent> <m:sCode>AM</m:sCode> <m:sName>The Americas</m:sName> </m:tContinent> </m:ListOfContinentsByNameResult> </m:ListOfContinentsByNameResponse> </soap:Body> </soap:Envelope> |
On Postman, this configuration with
the request and response should look like this:
This example uses XML envelopes for
the request and response. To modernize this API, we can import the WSDL
definition of the API into Azure APIM. To get the WSDL file, just add the wsdl
parameter to the query string and send a GET request. The response should be an
XML schema file which describes the API operations and data types.
http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?wsdl
Import the WSDL
Note: The following steps should be
done on a subscription that has an API Management service configured.
To import the API schema definition
into APIM, open Azure Portal, API Management console. Click on the API link to
open the existent API definitions. From this view, click on Add API and select
the WSDL option. Configure the popup information as shown on the image below.
Make sure to use the URL that has the wsdl parameter on the query string. When
ready, press create to generate the API definition with policies.
Note: Make sure to use the URL that has the wsdl parameter on the query string
A new API with the name of
ContryInfoService should get created. Click on that name to display the
operations that are available from this API. Check the settings for this API
and make a note of the Base URL. This is the URL that should be used to send
request to the new API.
We are interested in finding the
ListOfContinentsByName operation. This is the same API that we use for the
Postman validation. Once selected,
review the inbound and outbound policies by clicking on the code icon as shown
below:
Policy File
APIM Policy Gist
The policy has an inbound and
outbound node. The inbound node uses a liquid template to transform the
incoming payload into a SOAP envelope which is required by the SOAP
service. The outbound node also uses a
liquid template to transform the XML response into a JSON payload which is then
sent back to the calling application. The markup use on the liquid template has
many features, and we could no cover all the details here. For this simple example, we can see how a new
JSON document is created by adding the items from the continents collection.
We should now have a JSON API ready,
but we are not yet RESTful. The SOAP service requires documents to be send for
every request, as a result it uses POST request method for even reading
information. A RESTful service should instead be able to get the continent
information using a GET request method instead of using POST which should only
be used for creating new resources. We should remove that constraint by using APIM
to change that configuration as well. Let’s load the operation settings and
click on the Frontend configuration. From this configuration, we can change the
request method from POST to GET, and even change the URL route to something
that aligns with our naming conventions. Also notice that on the inbound policy, we add the set-method policy to indicate that even if the request came in as a GET request, we want to forward this as a POST request which is what the SOAP API expects. The new setting should look as
follows:
All should be setup to make requests
to the new API. If no extra configuration was done like adding a subscription
key, and the APIM resource was not created in a private subnet, we should be
able to access the API from the internet. Let’s load our tool of choice and
make a request to the new API. Get the Base URL from the setting and append the
operation name. That is the new RESTful route. We can now configure a request
with the header Content-Type: application/json and set the method to GET. There
is no need to add anything on the body as there is no JSON payload to send
during a GET operation. This is what the new configuration should look like.
As we can see the results show a
list of continents, but instead of showing an XML document it is now showing
the data on a JSON document.
Conclusion
Modernizing a legacy SOAP API can be
a very expensive and long project. In cases when it is needed to accelerate the
solution and minimize the risks, Azure API Management provides a solid
approach. This service provides capabilities to create a REST-Base API,
policies to handle document transformation and enhances the security of the APIs.
All this can be achieved without having to decommission the existent legacy
SOAP API and getting a business to provide modern APIs to its customers.