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

Calling a Java Method From XSLT in Mule

DZone's Guide to

Calling a Java Method From XSLT in Mule

The Xalan extension in our XSL file can call any Java method and get the value returned to it—which it can use to fill any node or attribute value.

Free Resource

Discover how Microservices are a type of software architecture where large applications are made up of small, self-contained units working together through APIs that are not dependent on a specific language. Brought to you in partnership with AppDynamics.

XSLT (Extensible Stylesheet Language Transformation) is an amazing language for transforming XML documents into other XML documents. Mule applications support using XSL files for transformation using its XSLT transformer within a flow.

Within XSLT, there is a feature of calling Java methods with the Xalan extension. With this extension, we can pass arguments to the extension implementation and return a value with the Java method. We can use extension functions to return a value (of any type) that XSLT can interact with directly and place as a node value or an attribute value of the transformed XML.

In this blog, we will demonstrate how to transform an XML input payload into another XML format along with how to call Java methods, get the return value from them, and place them as a node value in the output XML using XSLT transformer in Mule.

We will take a simple example. Our input XML payload is:

<?xml version="1.0"?>
<RootElement>
	<Name>Anirban Sen Chowdhary</Name>
</RootElement>

As this payload gets into our Mule application, it will get transformed into XML output:

<NewRootElement>
	<Name>Anirban Sen Chowdhary</Name>
	<Designation>MuleSoft Developer</Designation>
</NewRootElement>

As you can see above, the expected XML output contains an additional node called <Designation> with a value MuleSoft Developer. This will be created by XSLT transformer in our Mule application.

Going ahead, our Mule flow that will transform the XML above like this:

<spring:beans>
	<spring:bean name="myJava" class="com.test.TestClass"/>
</spring:beans>
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="CallingJavaFromXSLTFlow">
	<http:listener config-ref="HTTP_Listener_Configuration" path="/xsl" doc:name="HTTP"/>
	<object-to-string-transformer doc:name="Object to String"/>
	<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" outputEncoding="UTF-8" doc:name="Transform from" 
   xsl-file="Transform.xslt" encoding="UTF-8" returnClass="java.lang.String" 
   transformerFactoryClass="org.apache.xalan.processor.TransformerFactoryImpl">
		<mulexml:context-property key="myJava" value="#[app.registry.myJava]" />
		<mulexml:context-property key="designation" value="MuleSoft Developer" />
	</mulexml:xslt-transformer>
	<logger message=" #[payload] " level="INFO" doc:name="Logger"/>
</flow>

As you can clearly see in the flow, the input XML flow will pass the XSLT transformer, where it will get transformed into the expected output XML with additional node added into it.

Also, if you look closely, you will find that we have used a Java class "com.test.TestClass", which is defined by the Spring beans. We will be calling all the methods defined in this class from our XSL file.

One important thing here is to note that, in our XSLT transformer, we need to define:

transformerFactoryClass="org.apache.xalan.processor.TransformerFactoryImpl"

...as we are using the Xalan extension for XSLT.

Here is our Java class with two methods that will be called in our XSL file:

package com.test;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TestClass {
 private static final Logger log = LogManager.getLogger(TestClass.class);

 public String myDesignation(String designation) {
  log.info(designation);
  return designation;
 }

 public String myName(String name) {
  log.info(name);
  return name;
 }
}

The first method, myDesignation(), will return the designation value for the <Designation> node in the expected XML output. The value will be passed directly as a parameter in the XSLT transformer in the Mule flow:

<mulexml:context-property key="designation" value="MuleSoft Developer" />

We will also be passing the Spring bean reference of our Java class a parameter in the XSLT transformer in the Mule flow:

<mulexml:context-property key="myJava" value="#[app.registry.myJava]" />

The XSL file that we will keep under the src/main/resources folder of Mule application is as follows:

<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:redirect="org.apache.xalan.xslt.extensions.Redirect"
	xmlns:java="http://xml.apache.org/xslt/java" exclude-result-prefixes="java"
extension-element-prefixes="redirect">
	<xsl:output omit-xml-declaration="yes" indent="yes" />
	<xsl:param name="myJava" />
	<xsl:param name="designation" />
	<xsl:template match="/">
		<NewRootElement>
			<Name>
				<xsl:value-of select="java:myName($myJava,/RootElement/Name)" />
			</Name>
			<Designation>
				<xsl:value-of select="java:myDesignation($myJava,$designation)" />
			</Designation>
		</NewRootElement>
	</xsl:template>
</xsl:stylesheet>

Here, in our XSL file, we can see we are receiving the parameters (the Spring beans reference and designation value) we passed from our XSLT transformer earlier in Mule flow:

<xsl:param name="myJava" />
<xsl:param name="designation" />

Now, we are calling myName() from the Java class and passing the name as a parameter in it using XPATH, which extracts the value from the name node of the input XML:

<Name>
	<xsl:value-of select="java:myName($myJava,/RootElement/Name)" />
</Name>

Note: Here, in the method myName($myJava,/RootElement/Name), the first parameter is the Spring bean reference $myJava that refers the Java class that we need to look for in the Spring beans.

Similarly, we are adding an additional node in our XSL file called Designation and calling the Java class method myDesignation(), passing the $designation as a parameter to the method:

<Designation>
	<xsl:value-of select="java:myDesignation($myJava,$designation)" />
</Designation>

And that's it. We are done!

We will be testing our flow with the Postman REST client as follows. When we put the following XML as an input and hit the Mule application with the URL http://localhost:8081/xsl, we will get the transformed XML with the additional node <Designation> in it:

Image title

As we can see, the output XML contains both the nodes (name and designation) and the value of both these nodes are filled by calling both the Java method myDesignation()and myName().

We can see that using the Xalan extension in our XSL file, the Xalan processor can call any Java method and get the value returned to it, which it can use to fill any node or its attribute value. In the Mule application, it is very easy to define and refer the Java class in Spring beans with which we can directly pass the bean reference to the XSLT that help to call the methods of the class.

Discover the six challenges and best practices in managing microservice performance, brought to you in partnership with AppDynamics.

Topics:
mule ,xml ,xslt ,integration ,tutorial ,xalan

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

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

{{ parent.tldr }}

{{ parent.urlSource.name }}