XSLT Interceptor allows easy integration with other XML protocols using XSL Transformations. This feature can help application integration developers make on-the-fly transformations between two mutually incompatible Web services.
Imagine an example where a user has two Web services with incompatible operations. The user writes an XSLT style sheet and sets up an XSLT Interceptor that will transform SOAP messages on-the-fly to be compatible with the other side.
There are several possible ways to use and configure an XSLT Interceptor. The section Persistent Configuration describes how you can configure an XSLT Interceptor at deployment time. On the other hand, the section Runtime Configuration shows configuration with the help of the runtime API.
To utilize XSLT Interceptor, you must install the XSLT-Interceptor component. (For more information, please see XSLT-Interceptor in the Components chapter.)
This section describes usage of the predefined XSLTInterceptor package and the more flexible custom configuration of XSLT Interceptor.
The easiest way to use XSLT Interceptor is by using our XSLTInterceptor package, which should be deployed during WSO2 SOA Enablement Server installation if you have chosen to install the XSLTInterceptor component. To use the XSLTInterceptor package in your application, create a dependency on it in your package's deployment descriptor and write the appropriate style sheets.
The deployment descriptor of the package that depends on the XSLTInterceptor package is shown in Example 281, Deployment Descriptor.
Example 281. Deployment Descriptor
<package name="ToDoListService" ... xmlns:xslt="http://systinet.com/wasp/app/xsltinterceptor" ... > ... <dependency ref="xslt:xsltinterceptor" version="1.0"/> ... </package>
Interceptors can process both incoming and outgoing messages for a service. XSLT Interceptor performs a transformation when a style sheet for the given direction is specified. The style sheet filename for the in direction must be in.xsl; for the out direction, the name must be out.xsl. These files should be placed in the root of the package structure that uses the interceptor, see Figure 29.
To use XSLT Interceptor on the client side, place the file WASP_HOME/lib/xsltinterceptor.jar in the Java VM CLASSPATH variable, together with the JAR file of your package; then start the client program. Of course, as mentioned above, your package must depend on the XSLTInterceptor package. WSO2 SOA Enablement Server automatically finds these packages and takes appropriate steps to use them. More information about client packages can be found in the section Client Package.
Another way to use XSLT Interceptor on the client side is to add your in.xsl and out.xsl to the copy of the WASP_HOME/lib/xsltinterceptor.jar file and place this copy in the Java VM CLASSPATH variable. In this case, you do not have to create the client package with a dependency on the XSLTInterceptor package, because a default one will be used.
The custom configuration of XSLT Interceptor can be used when you define more then one service endpoint or instance in your package, and all of them need their own XSL Transformation. In this case you must specify an interceptor instance for all service endpoints or instances. Example 282 shows the deployment descriptor of HelloService with two service endpoints.
Example 282. Custom Configuration of XSLT Interceptor
<?xml version="1.0" encoding="UTF-8"?> <package name="HelloService" targetNamespace="http://wso2.com/package/example/ applicationIntegration/xsltinterceptor" version="1.0" xmlns="http://wso2.com/wasp/package/1.1" xmlns:ns0="http://wso2.com/wsdl/example/applicationIntegration/xsltinterceptor/" xmlns:tns="http://wso2.com/package/example/applicationIntegration/xsltinterceptor" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsd:schemaLocation="http://wso2.com/wasp/package/1.1"> <license>http://wso2.com</license> <!-- HelloService1 endpoint --> <service-endpoint name="HelloService1" path="/HelloService1" processing="tns:HelloService1_processing" service-instance="tns:HelloService_inst" type="java"> <wsdl service="ns0:JavaService" uri="HelloService.wsdl"/> </service-endpoint> <!-- HelloService2 endpoint --> <service-endpoint name="HelloService2" path="/HelloService2" processing="tns:HelloService2_processing" service-instance="tns:HelloService_inst" type="java"> <wsdl service="ns0:JavaService" uri="HelloService.wsdl"/> </service-endpoint> <!-- HelloService service instance --> <service-instance implementation-class="examples.applicationIntegration.HelloService" name="HelloService_inst"/> <!-- definition and configuration of xslt interceptor for endpoint HelloService1 --> <interceptor direction="in out" implementation-class="com.idoox.wasp.interceptor.XSLTInterceptor" name="XSLTInterceptorInstance1"> <configuration> <config> <inputXSL>customIn1.xsl</inputXSL> <outputXSL>customOut1.xsl</outputXSL> </config> </configuration> </interceptor> <!-- definition and configuration of xslt interceptor for endpoint HelloService2 --> <interceptor direction="in out" implementation-class="com.idoox.wasp.interceptor.XSLTInterceptor" name="XSLTInterceptorInstance2"> <configuration> <config> <inputXSL>customIn2.xsl</inputXSL> <outputXSL>customOut2.xsl</outputXSL> </config> </configuration> </interceptor> <!-- HelloService1 processing --> <processing name="HelloService1_processing"> <use ref="tns:XSLTInterceptorInstance1"/> </processing> <!-- HelloService2 processing --> <processing name="HelloService2_processing"> <use ref="tns:XSLTInterceptorInstance2"/> </processing> </package>
The custom configuration is also applicable on the client sXSLT-Interceptoride, as you can see in Example 283.
Example 283. Custom Client Configuration of XSLT Interceptor
<?xml version="1.0" encoding="UTF-8"?> <package client-package="true" name="HelloServiceClient" targetNamespace="http://wso2.com/package/example/ applicationIntegration/xsltinterceptor" version="1.0" xmlns="http://wso2.com/wasp/package/1.1" xmlns:ns0="http://wso2.com/wsdl/example/applicationIntegration/xsltinterceptor/" xmlns:tns="http://wso2.com/package/example/applicationIntegration/xsltinterceptor" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsd:schemaLocation="http://wso2.com/wasp/package/1.1"> <license>http://wso2.com</license> <!-- service client --> <service-client port-type="ns0:HelloService" processing="tns:HelloService_processing"/> <!-- definition and configuration of xslt interceptor for HelloService service client --> <interceptor direction="in out" implementation-class="com.idoox.wasp.interceptor.XSLTInterceptor" name="XSLTInterceptorInstance"> <configuration> <config> <inputXSL>customIn.xsl</inputXSL> <outputXSL>customOut.xsl</outputXSL> </config> </configuration> </interceptor> <!-- HelloService processing --> <processing name="HelloService_processing"> <use ref="tns:XSLTInterceptorInstance"/> </processing> </package>
The service's configuration via the runtime API is transient: when the server is shut down, this configuration ceases to exist and the service needs to be reconfigured when the server is restarted. Runtime configuration of XSLT Interceptor on the client side is shown in a simple way in Example 284 and on the service side in Example 285. A client for the service-side configuration is shown in Example 286. All of these examples use the XSLTInterceptor(java.io.InputStream, java.io.InputStream) constructor, where the first parameter is the input stream of the style sheet for the in direction and the second parameter is the input stream for the out direction.
Example 284. Client Configuration
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.xsltinterceptor; import com.idoox.wasp.interceptor.XSLTInterceptor; import example.basics.invocation.HelloService; import org.systinet.wasp.webservice.Interceptors; import org.systinet.wasp.webservice.Registry; import org.systinet.wasp.webservice.ServiceClient; import java.io.FileInputStream; public final class HelloClient { private static String serviceWSDLPath = "/demo/basic/HelloService/wsdl"; public static void main(String[] args) throws Exception { String serverURL = System.getProperty("wso2.demo.server.url", "http://localhost:6060"); ServiceClient serviceClient = ServiceClient.create(serverURL + serviceWSDLPath, HelloService); // create XSLTnterceptor and setup service client XSLTInterceptor xsltInterceptor = new XSLTInterceptor(new FileInputStream("in.xsl"), new FileInputStream("out.xsl")); serviceClient.getInterceptors() .insert(xsltInterceptor, Interceptors.DIRECTION_INOUT); // lookup service HelloService helloService = (HelloService) Registry.lookup(serviceClient); // call HelloServiceImpl and print out a response message System.out.println(helloService.hello("Hello service!")); } }
Example 285. Service Configuration
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.xsltinterceptor; import com.idoox.wasp.interceptor.XSLTInterceptor; import org.idoox.wasp.types.RequestMessageAttachment; import org.systinet.wasp.webservice.Current; import org.systinet.wasp.webservice.Interceptors; import org.systinet.wasp.webservice.ServiceEndpoint; import java.io.IOException; import javax.xml.transform.TransformerConfigurationException; public class HelloServiceImpl { private final static String HELLO_WORLD = "Hello World, this is WSO2" + " SOA Enablement Service. You have sent me : "; // runtime registered interceptor's name XSLTInterceptor xsltInterceptor; /** * Registers XSLTInterceptor * @param inXSL the stylesheet filename for the in direction * @param outXSL the stylesheet filename for the out direction * @throws IOException when an error occurs * @throws TransformerConfigurationException when an error occurs */ public void init( RequestMessageAttachment inXSL, RequestMessageAttachment outXSL) throws IOException, TransformerConfigurationException { // gets endpoint ServiceEndpoint endpoint = Current.getServiceEndpointContext() .getServiceEndpoint(); // creates XSLTInterceptor instance xsltInterceptor = new XSLTInterceptor( inXSL.getData(), outXSL.getData()); // inserts interceptor endpoint.getInterceptors() .insert(xsltInterceptor, Interceptors.DIRECTION_INOUT); } /** * Removes XSLTInterceptor */ public void clean() { Interceptors interceptors = Current.getServiceEndpointContext() .getServiceEndpoint() .getInterceptors(); interceptors.remove(xsltInterceptor); } /** * Returns 'Hello world' message * @param message * @return 'Hello world' */ public String hello(String message) { return HELLO_WORLD + message; } }
Example 286. Client for Service Configuration
// Copyright WSO2 Inc. All rights reserved. // Use is subject to license terms. package example.applicationIntegration.xsltinterceptor; import org.idoox.wasp.types.RequestMessageAttachment; import org.systinet.wasp.webservice.Registry; import java.io.FileInputStream; public class HelloServiceClient { private static String serviceWSDLPath = "/demo/basic/HelloService/wsdl"; public static void main(String[] args) throws Exception { String serverURL = System.getProperty("wso2.demo.server.url", "http://localhost:6060"); // lookup of HelloServiceImpl HelloService helloService = (HelloService) Registry.lookup(serverURL + serviceWSDLPath, HelloService.class); // init service configuration RequestMessageAttachment attachmentIn = new RequestMessageAttachment(); attachmentIn.setData(new FileInputStream("in.xsl")); RequestMessageAttachment attachmentOut = new RequestMessageAttachment(); attachmentOut.setData(new FileInputStream("out.xsl")); helloService.init(attachmentIn, attachmentOut); // call service and print out a response message from HelloService System.out.println(helloService.hello("Hello service!")); // clean service configuration helloService.clean(); } }
For details about the runtime API, see Runtime Publishing under Publishing Web services in the Developer's Guide. This section begins with the Registry chapter.
The following list shows the priority when more types of configuration occur for one XSLT Interceptor instance:
Runtime configuration
Custom configuration
Use of the XSLT Interceptor
XSLT Interceptor passes the following parameters to the style sheets:
PARAM_URI
URI of connection whose messages are intercepted
PARAM_PATH
path of the URI
PARAM_CONTEXT_PATH
context path of the URI
PARAM_LOCATION
location of the URI
More information about the meaning of parameters can be found in the Javadoc for org.idoox.transport.URI.
There is more information about Interceptors in the chapter Interceptors in the Message Processing section.
A demo in the directory WASP_HOME/demo/advanced/xslt shows the use of XSLT Interceptor to transform outgoing SOAP messages to HTML.
![]() | Note |
---|---|
In the case of Multi-part messages, transformation is applied only to the first part of the message. |
WSO2 SOA Enablement Server comes bundled with the Xalan XSLT processor, Version 2.5.1. It is located in the file xalan.jar and it is automatically loaded together with wasp.jar. However, it is possible to use a different XSLT processor, such as Saxon.
To do this on the client side, place the JAR file containing your XSLT processor in your client CLASSPATH and on server side place the JAR in WSO2 SOA Enablement Server CLASSPATH. Then you can use both persistent and runtime configuration of the XSLT Interceptor. Example 287 shows persistent configuration for Saxon. Note the transformerFactory and parserFactory elements which specify the appropriate implementation classes.
Example 287. Persistent Configuration for Saxon
<package name="HelloService" ...> ... <!-- definition and configuration of xslt interceptor --> <interceptor name="XSLTInterceptorInstance" implementation-class="com.idoox.wasp.interceptor.XSLTInterceptor" direction="in out"> <configuration><config> <inputXSL>in.xsl</inputXSL> <outputXSL>out.xsl</outputXSL> <transformerFactory>com.icl.saxon.TransformerFactoryImpl</transformerFactory> <parserFactory>com.icl.saxon.aelfred.SAXParserFactoryImpl</parserFactory> <documentBuilderFactory/> </config></configuration> </interceptor> ... </package>
In the case of runtime configuration, you should use the XSLTInterceptor(InputStream inputXSL, InputStream outputXSL, String transformerFactory, String parserFactory, String documentBuilderFactory) constructor for setting particular values. It is not necessary to specify all the properties, so you can set null.
Another way, on the client side, is placing the JAR file containing the XSLT processor as the first entry in your client classpath. It is necessary that this JAR file contains the META-INF/services directory, setting the properties javax.xml.transform.TransformerFactory and javax.xml.parsers.SAXParserFactory to the implementation class of your XSLT processor transformer factory and SAX parser factory. This is already true for Saxon 6.2 and above, but you may need to add this manually to other XSLT processor implementations.