Announcement Announcement Module
Collapse
No announcement yet.
PayloadTransformingInterceptor for Client? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • PayloadTransformingInterceptor for Client?

    I am writing a webservice client and need to perform an XSLT transform on the response payload BEFORE it is unmarshalled. Is there anything like the PayloadTransformingInterceptor for the client or any suggestions for how to accomplish this?
    Thanks!
    -Ed

  • #2
    I never got any response, but here is what I came up with. I extended the Jaxb2Marshaller class to override the unmarshal method and then just did my transform prior to handing off to the super.unmarshal() method. The code for my class is below. I called it "XslTransformingMarshaller". In your config, you just need to set this class as the unmarshaller and marshaller for your WebServiceTemplate and then set the umarshalXslt to your XSLT. Optionally, you can specify a transformerFactoryClass (in our case this was necessary because we're running in an ADF/Weblogic container environment and the default transformer doesn't handle DOMSource. Note that my class below uses DOMSource and DOMResult so you may have performance problems if you are parsing large documents, but this was not an issue for us.

    This seems to work pretty well for me. I have done some initial testing and it appears to be performant and threadsafe, but no guarantees.

    Code:
    import org.springframework.core.io.Resource;
    import org.springframework.oxm.UncategorizedMappingException;
    import org.springframework.oxm.XmlMappingException;
    import org.springframework.oxm.jaxb.Jaxb2Marshaller;
    import org.springframework.oxm.mime.MimeContainer;
    import org.springframework.xml.transform.TransformerHelper;
    
    import javax.xml.transform.*;
    import javax.xml.transform.dom.DOMResult;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamSource;
    import java.io.IOException;
    
    /**
     * This class provides a way to intercept and transform a web service
     * message with XSLT prior to unmarshalling.
     * Can be used in place of the Jaxb2Marshaller in a WebServiceTemplate.
     * This marshaller should be threadsafe as it uses the threadsafe Templates
     * class and creates a new Transformer for each message.
     */
    public class XslTransformingMarshaller extends Jaxb2Marshaller {
        private Templates unmarshalTemplates;
        private Class<? extends TransformerFactory> transformerFactoryClass;
    
        /**
         * Allows you to set a specific TransformerFactory implementation if you need something specific.
         * This is optional. By default the transformer will be whatever is available at runtime based
         * on the jvm or system settings.
         * @param transformerFactoryClass
         */
        public void setTransformerFactoryClass(Class<? extends TransformerFactory> transformerFactoryClass) {
            this.transformerFactoryClass = transformerFactoryClass;
        }
    
        /**
         * Use this method to set the XSLT you want to use for transforming the message
         * prior to unmarshalling.
         * @param unmarshalXslt
         * @throws IOException
         * @throws TransformerException
         */
        public void setUnmarshalXslt(Resource unmarshalXslt) throws IOException, TransformerException, ClassNotFoundException {
            //Creates a Templates object that is a threadsafe factory for Transformers based on this XSLT
            Source xsltSource = new StreamSource(unmarshalXslt.getInputStream());
            TransformerFactory transFact;
            if(transformerFactoryClass != null) {
                TransformerHelper helper = new TransformerHelper(transformerFactoryClass);
                transFact = helper.getTransformerFactory();
            } else {
                transFact = TransformerFactory.newInstance();
            }
            this.unmarshalTemplates = transFact.newTemplates(xsltSource);
        }
    
        @Override
        public Object unmarshal(Source source, MimeContainer mimeContainer) throws XmlMappingException {
            if(unmarshalTemplates == null) return super.unmarshal(source, mimeContainer);
    
            DOMSource transformedSource;
            try {
                //Transform the response
                Transformer transformer = unmarshalTemplates.newTransformer();
                DOMResult resultOfTransform = new DOMResult();
                transformer.transform(source, resultOfTransform);
                transformedSource = new DOMSource(resultOfTransform.getNode());
            } catch (TransformerException e) {
                throw new UncategorizedMappingException("Could not unmarshal due to an exception with the Transformer.", e);
            }
            return super.unmarshal(transformedSource, mimeContainer);
        }

    Comment

    Working...
    X