Our Tryst With AWS API Gateway and XML Transformation
See a solution to the issue of not being able to transform XML to JSON with AWS API Gateway.
Join the DZone community and get the full member experience.
Join For FreeUnfortunately, the world has not yet upgraded itself to JSON, and a considerable amount of the world still uses XML-based SOAP services.
You might also enjoy: Payload Transformation: JSON to XML
Background
Our tryst with XML and AWS API Gateway began when our client wanted to replace a Java-based middle layer application, which was proxying legacy SOAP services with AWS API Gateway. The middle layer application was calling the SOAP services using Apache axis2 client. Our use case looked like this:
- Consumers will communicate with Gateway using only JSON.
- Gateway will communicate with legacy backend SOAP services only using application/XML.
The Problem
At first, everything looked fine. We quickly integrated the backend SOAP service from Gateway. But then, we realized some great limitations of AWS API GW for our use case:
- It does not support XML to JSON transformation.
- It does not parse XML content to modify it, though velocity scripting language provides a great deal of flexibility to modifying JSON.
With the limitations provided, all the great capabilities of AWS API Gateway were not enough for us.
Possible Solutions
Use Lambda — Call SOAP service and data transformation in lambda and integrate it into GW. We found quite a few blogs suggesting using Lambda for this kind of transformation. Though lambdas are great, in our use case, it meant:
Write code for data transformation for 100+ backend SOAP services. Maintaining JSON to SOAP request transformation for every service at Lambda meant more code upkeep and not leveraging the power of GW.
Also, AWS API GW does not support sending XML in raw format to lambda. XML can be put into a JSON by escaping all spaces and double quotes making JSON difficult to manage and understand.
With the approach looking difficult, we landed on the below solution.
Actual Solution
Beanstalk to the Rescue
We created a generic POST type REST service that accepts application/XML and:
- Calls a SOAP service using Spring Boot and Apache HTTP client.
- Converts the response SOAP response from the backend service to JSON, using Jackson fasterxml.
We deployed this service on a beanstalk. Luckily, we had other applications on beanstalk, and adding another service was not a roadblock for us.
@PostMapping(path="generic/rest")
public ResponseEntity<?> getBusinessValue(@RequestBody String soapRequest, @PathVariable("service") String service) throws ClientProtocolException, IOException {
HttpClient client = HttpClients.custom().build();
HttpEntity httpEntity = new StringEntity(soapRequest);
HttpPost postRequest = new HttpPost(service_path);
postRequest.setEntity(httpEntity);
HttpResponse httpResponse = client.execute(postRequest);
HttpEntity responseEntity = httpResponse.getEntity();
String entiryString = EntityUtils.toString(responseEntity);
JsonNode response = fetchFromSoapResponse(entiryString);
return new ResponseEntity<>(response, responseHeaders, HttpStatus.OK);
}
public static JsonNode fetchFromSoapResponse(String xmlString) throws IOException {
XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(xmlString.getBytes());
return node;
}
Our solution looked like:
GW accepts the JSON, and using the mapping template transforms the JSON into XML. GW integrates the above-mentioned REST Service deployed on beanstalk with the transformed XML as payload. This beanstalk does the magic of calling the backend SOAP service and converts the SOAP response to JSON. GW receives this JSON and passes it back to the consumers.
The following is a sample model:
The following is the sample mapping transformation of XML, which is sent to a POST type REST service deployed on beanstalk:
The following response is returned by GW:
Conclusion
The solution we used is no silver bullet, but given the limitations provided by AWS API Gateway, this is what we could offer.
Further Reading
Opinions expressed by DZone contributors are their own.
Comments