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.
Join the DZone community and get the full member experience.
Join For FreeXSLT (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:
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.
Opinions expressed by DZone contributors are their own.
Comments