Wednesday, February 21, 2018

Spring Integration and XSLT with parameters

I have had the opportunity to use Spring Integration to execute the XSLT on the projects I've been on. It is actually quite easy and very fast. It allows you to pass in properties to the XSLT, which can be very useful. For instance, maybe there is a database lookup that you need to perform to get a value, or perhaps there are values in the Headers that are needed in the transformed message.

When dealing with XML it is always a good idea to have an XSD the defines what the valid XML should look like. There should be an XSD for the incoming XML and another XSD for the transformed XML. It is good practice to perform XSD validation on both to ensure the messages that are being received and the messages that are being sent conform to the XSD specifications.

Let's start with the Spring Configuration. The following spring code was part of a chain, so it doesn't have the input and output channels explicitly defined. There are a few interesting parts that some may not be familiar with I'd like to point out. First, this code is making use of properties that get substituted at run time by a Spring PropertyPlaceholderConfigurer. Both of the property's below are paths, and the values are the relative path inside the class path.

The second interesting part is the parameter that is being passed in. It is accessing a value defined in a Java class, this could also just as easily call a Java method to return a value. Again the class name includes the relative path from the class path.

<int-xml:validating-filter schema-location="${my.relative.incoming.xsd.file.location}" throw-exception-on-rejection="true"/>
<int-xml:xslt-transformer          
    xsl-resource="${my.relative.xslt.file.location}" >
    <int-xml:xslt-param name="trackingId" 
        expression="headers.get(T(com.mycompany.package.MyClass).MESSAGE_ID)"/>
</int-xml:xslt-transformer>
<int-xml:validating-filter schema-location="${my.relative.outgoing.xsd.file.location}" throw-exception-on-rejection="true"/>

The above code will first validate the incoming XML against the incoming XSD. If it validates correctly it will then perform the XSLT transformation, and finally it will validate that the outgoing XML matches what is expected from the outgoing XSD. That's really all there is to it.

Some will wonder what happens if it fails either validation or the transformation. It will throw an error and the error handling that was defined for the flow will do what ever it was configured to do. Error handling is out of scope for this blog.

The below XSLT demonstrates how to receive the parameter into the XSLT, and how to use it in the XSLT. The line above the template match line, is where the variable is received by the XSLT. To use the variable you just access it using $trackingId.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
    <xsl:param name="trackingId" />
    <xsl:template match="/weatherDetail">
        <WeatherResponse>
            <Header>
                <Timestamp>
                    <xsl:value-of select="current-dateTime()" />
                </Timestamp>
            </Header>
            <Body>
                <externalId>
                    <xsl:value-of select="$trackingId" />
                </externalId>
            </Body>
        </WeatherResponse>
    </xsl:template>
</xsl:stylesheet> 

No comments: