Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Service Call From XSLT Inside a Mule Application

DZone's Guide to

Service Call From XSLT Inside a Mule Application

Learn how to make a service call from XSLT in a Mule application to get information from a REST service to use in an XSLT transformation.

Free Resource

Modernize your application architectures with microservices and APIs with best practices from this free virtual summit series. Brought to you in partnership with CA Technologies.

XSLT (Extensible Stylesheet Language Transformation) is a language for transforming XML documents into other XML documents, or other formats like HTML for web pages, plain text, or XSL Formatting Objects. Mule applications support using XSL files for transformation using its XSLT transformer within a flow.

This blog is for scenarios when you need to make a service call from XSLT to get some information from a REST service and use it in your XSLT for processing or just displaying. XSLT gives the functionality of making a service call by using the select="document(concat(.....))" option. This is applicable for the HTTP GET method only.

We will explain by using a simple example. We will pass some dummy countryCode in the request XML and in response we will get the countryName. The input XML payload is:

<?xml version="1.0"?>
<Wrapper>
<CountryCode>in</CountryCode>
</Wrapper>

The expected output from the Mule application is:

<NewWrapper xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <CountryName>India</CountryName>
</NewWrapper>

The Mule flow to expose the endpoint (HTTP_Listener_Configuration in this example) and use XSLT (NewFile.xsl) to transform the input XML to desired output XML.

<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8080" doc:name="HTTP Listener Configuration"/>
<flow name="testbmFlow1">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/xsltchk" doc:name="HTTP"/>
        <object-to-string-transformer doc:name="Object to String"/>
        <mulexml:xslt-transformer xsl-file="NewFile.xsl" maxIdleTransformers="2" maxActiveTransformers="5" doc:name="XSLT">
        <mulexml:context-property key="code" value="#[xpath3('Wrapper/CountryCode')]"/>
        </mulexml:xslt-transformer>
        <object-to-string-transformer doc:name="Object to String"/>
        <logger message="#[payload]" level="INFO" doc:name="Logger"/>
    </flow>

We are passing this countryCode as a parameter to XSLT to use. 

Below is our XSLT file (NewFile.xsl) :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" />
    <xsl:param name="code"/>
<xsl:template match="/">
<NewWrapper>
        <xsl:variable name="REST_response" select="document(concat('http://localhost:8080/countryservice?key=',$code))"/>
<CountryName>
<xsl:value-of select="$REST_response/VALUE"/>
</CountryName>
</NewWrapper>
</xsl:template>
</xsl:stylesheet>

In the XSLT, at line 4, we are using the countryCode which is passed from the Mule flow. Now, in line 10, what does the $REST_response/VALUE mean? The service is returning countryName within a tag <VALUE>, so we need to use this xpath to get countryName.

Now I will explain the service exposed in Mule to use to get countryName by passing countryCode. Code for the exposed service:

<flow name="countryCodeServiceFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/countryservice" doc:name="HTTP"/>
        <object-to-string-transformer doc:name="Object to String"/>
        <custom-transformer class="ca.rsagroup.esb.processor.lookup.CountryNameLookup" doc:name="Java">
        </custom-transformer>
    </flow>

Line 4 has a custom transformer called CountryNameLookup.java. In this class, we have used the AbstractMessageTransformer interface of Mule and added some dummy countryCode key and countryName values.

Code for CountryNameLookup:

public class CountryNameLookup extends AbstractMessageTransformer {
	private Map < String,
	String > countryNameMap;
	public CountryNameLookup() {
		countryNameMap = new HashMap < String,
		String > ();
		countryNameMap.put("in", "India");
		countryNameMap.put("us", "United Stated of America");
		countryNameMap.put("nz", "New Zealand");
		countryNameMap.put("aus", "Australia");
	}@Override
	public Object transformMessage(MuleMessage message, String outputEncoding)
	throws TransformerException {
		System.out.println("*** call to CountryNameLookup transformMessage method ******");
		String key = null;
		if (null != message) {
			Map query = (Map) message.getInboundProperty("http.query.params");
			query.get("key");
			key = (String) query.get("key");
			System.out.println("Key passed " + key + " value " + countryNameMap.get(key));
			String csioValue = countryNameMap.get(key);

			return "<VALUE>" + csioValue + "</VALUE>";
		}
		return null;
	}
}

That's all for this blog. Hope you found this article useful.

We can test our flow using soapUI. The testing URL is http://localhost:8080/xsltchk and you can see the countryName based on the countryCode you have passed in the request.

The Integration Zone is proudly sponsored by CA Technologies. Learn from expert microservices and API presentations at the Modernizing Application Architectures Virtual Summit Series.

Topics:
java ,xslt ,rest services ,xml ,integration ,mule

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}