Note: The entire codebase for the application can be found here — https://github.com/mrsauravsahu/blog-modernizing-soap-apis
Introduction
The Internet is made up of a large number of interconnected systems, all running under various conditions — hardware, software, security, configuration, etc.,. Communication between these systems happens using various standards, which have evolved over time.
Throughout the years, there have been many protocols to standardize the exchange of information between systems over the Web. To name a few, these would be SOAP, RPC, REST, WebSockets, GraphQL, gRPC, etc.
SOAP
The Simple Object Access Protocol [source], as the name suggests, a simple protocol to help ease the exchange of structured information between two systems on the Internet.
SOAP uses XML (eXtensible markup language) format for requests and responses.
Back to 2023
It’s highly likely that you wouldn’t have come across SOAP at all incase all the systems you’re integrating with are fairly new, and provide a REST or GraphQL based API.
But if you’re working with legacy systems which provide only SOAP based APIs, this one’s for you.
WHY?
The reasons for modernizing SOAP APIs is two-fold (add more in the comments if you have some more!)
- No more legacy SOAP interfacing code
- Easy to upgrade when REST / GraphQL APIs are available for the legacy system.
Time to Modernize!
Problem statement: Choosing a language to learn as an adult can be hard. There are many reasons one chooses to learn a certain language. One of the important outcomes of this choice are the ease of communication in the various geographies that speak this language.
So, let’s create an application to find out which countries speak a certain language, this helping you start your language learning journey!
Here’s the app we’ll be building —
Follow me on Duolingo 🦉 if you’re into language learning as well https://www.duolingo.com/profile/mrsauravsahu
I’ve taken an example SOAP API I found online for this example, as writing one by hand would be the total opposite direction 😂, but many languages do support XML support, so just know that that is still possible (even though you would have to have a good list of reasons for writing a SOAP API in 2023)
You can find the API description in this WSO/WSDL (Web Service Objects, Web Service Description Language) link —http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso, which is another XML object describing the various operations in the SOAP API — the Swagger of the SOAP world if you will.
This WSDL has two main versions — 1.1 and 1.2. I’ll focus on using v1.2 as that’s the latest, but you’ll have to check what is supporting in your APIs.
The WSDL contains various operations to query data about continents, countries, currency and languages — you can import this into Postman by using the WSDL link as shown below.
We’re going to focus on this operation FullCountryInfoAllCountries — which returns a list of details about countries, languages are a whole lot of other details, even though all we need is the country name and the languages that are spoken in that country.
Enter GraphQL Mesh
GraphQL mesh is a tool to help bring in federation to a variety of APIs, from many data sources like SOAP, REST, GraphQL, or even PostgreSQL. To modernize our SOAP API, we’ll create a Mesh project and use the soap source handler (here’s a tutorial to get started https://the-guild.dev/graphql/mesh/docs/getting-started/overview) — suprisingly the mesh website also uses the same Countries SOAP API for its SOAP examples, coincidence!
I’ve created a .meshrc.yaml
file in my mesh project, along with the following packages:
- @graphql-mesh/cli
- @graphql-mesh/soap
- @graphql-mesh/transform-filter-schema
- graphql
The creates a federated GraphQL service on top of our countries SOAP APIs and makes it available to the consumers as a regular GraphQL service — without them having to know that it’s a SOAP API.
This also brings all the benefits of GraphQL like property aliasing, retrieving only the data that you want and what have you!
Although mesh can also help configure and modify the generated schema itself, I’m just aliasing the property names in my query.
Here’s the .meshrc.yaml
I’m using. To filter out the noise, I’m filtering to only a few operations that I think I’ll be using in my app.
sources:
- name: Countries
handler:
soap:
source: http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?wsdl
transforms:
- filterSchema:
filters:
- Query.CountryInfoService_CountryInfoService_CountryInfoServiceSoap12_ListOfLanguagesByName
- Mutation.CountryInfoService_CountryInfoService_CountryInfoServiceSoap12_FullCountryInfoAllCountries
You can start the dev server for mesh using the following command — ./node_modules/.bin/graphql-mesh dev
Note: You should be building the mesh server and using the built artifacts to run the mesh on production.
❯ ./node_modules/.bin/graphql-mesh dev
💡 🕸️ Mesh - Server Starting GraphQL Mesh...
💡 🕸️ Mesh Generating index file in TypeScript
💡 🕸️ Mesh - Server Serving GraphQL Mesh: http://0.0.0.0:4000
💡 🕸️ Mesh Writing index.ts for ESM to the disk.
💡 🕸️ Mesh Writing index.ts for CJS to the disk.
Once the dev server starts, you’ll see a graphiQL explorer on the URL mentioned and your GraphQL schema along with types will be generated behind the scenes.
Et voilà! Your GraphQL mesh is ready! Now your backend can hit this mesh and consume data on the Federated GraphQL layer.
Let me know if this interests you and what new possibilities this creates!
— Sahu, S