spring-bootapache-camelxslt-1.0jboss-eap-7

Unable to invoke extension function in XSLT


Our project is written in Spring Boot and we are integrating Apache Camel in Spring Boot. In our Camel route, we are receiving an XML from the source system, transforming that within XSLT and sending the XML output to target system. Within the XSLT we are using an extension function:

xmlns:exsl="http://exslt.org/common" 

We are deploying the project as war file in JBoss EAP. The prblem is the extension function is throwing the below exception when it is called:

javax.xml.transform.TransformerException: Extension function: '{http://exslt.org/common}node-set' can not be invoked when the XMLConstants.FEATURE_SECURE_PROCESSING feature is set to true.
    at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:186)
    at org.apache.xpath.axes.FilterExprIteratorSimple.executeFilterExpr(FilterExprIteratorSimple.java:116)
    at org.apache.xpath.axes.FilterExprWalker.setRoot(FilterExprWalker.java:131)
    at org.apache.xpath.axes.WalkingIterator.setRoot(WalkingIterator.java:157)
    at org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:265)
    at org.apache.xpath.axes.LocPathIterator.asIterator(LocPathIterator.java:269)
    at org.apache.xalan.templates.ElemForEach.transformSelectedNodes(ElemForEach.java:335)
    at org.apache.xalan.templates.ElemForEach.execute(ElemForEach.java:265)
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
    at org.apache.xalan.templates.ElemIf.execute(ElemIf.java:162)
    at org.apache.xalan.templates.ElemForEach.transformSelectedNodes(ElemForEach.java:425)
    at org.apache.xalan.templates.ElemForEach.execute(ElemForEach.java:265)
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
    at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
    at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
    at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
    at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
    at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
    at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
    at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272)
    at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358)
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711)
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275)
    at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253)
    at org.apache.camel.builder.xml.XsltBuilder.process(XsltBuilder.java:142)
    at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:103)
    at org.apache.camel.component.xslt.XsltEndpoint.onExchange(XsltEndpoint.java:149)
    at org.apache.camel.impl.ProcessorEndpoint$1.process(ProcessorEndpoint.java:71)
    at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:76)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:76)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
    at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
    at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
    at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97)
    at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:113)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

The versions of software we are using are as follows:

Spring Boot - 2.3.3.RELEASE Apache Camel: 2.25 1 XSLT: 1.0 JBoss EAP: 7.3.0

Please suggest how to solve this issue.


Solution

  • Id say that exception says it all

    You need to create yourself class like this:

    public final class XmlUtil {
    
        private static final Logger log = LoggerFactory.getLogger("XmlUtilLOG");
        
        protected XmlUtil() {
            // empty on purpose to avoid instatiation
        }
    
        private static class InstanceHolder {
            public static final XmlUtil INSTANCE = new XmlUtil();
            
            private InstanceHolder() {
                // only to hold instance
            }
        }
                
        private final ThreadLocal<TransformerFactory> transformerFactory = new ThreadLocal<TransformerFactory>() {
            @Override
            protected TransformerFactory initialValue() {
                TransformerFactory tf;
                try {
                    tf = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl",
                            XmlHelper.class.getClassLoader());
                } catch (TransformerFactoryConfigurationError e) {
                    logger.error("", e);
                    tf = TransformerFactory.newInstance();
                }
                try {
                    tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
                } catch (TransformerConfigurationException e) {
                    logger.error("transformer factory feature {} not supported: {}", 
                        XMLConstants.FEATURE_SECURE_PROCESSING,
                            e.getMessage());
                }
                return tf;
            }
        };
    
        private final ThreadLocal<DocumentBuilder> documentBuilder = ThreadLocal.withInitial(() -> {
            try {
                DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
                documentBuilderFactory.setIgnoringComments(true);           
           documentBuilderFactory.setIgnoringElementContentWhitespace(true);
                documentBuilderFactory.setNamespaceAware(true);
                documentBuilderFactory.setFeature(
                    XMLConstants.FEATURE_SECURE_PROCESSING, false);
                documentBuilderFactory.setFeature(
                    "http://apache.org/xml/features/disallow-doctype-decl", true);
                return documentBuilderFactory.newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                logger.error("Error on XML Document builder intialization", e);
                throw new XmlConfigurationException(e);
            }
        });
    
    
        public XmlUtil getInstance() {
            return InstanceHolder.INSTANCE;
        }
    
        public Document transform(Node source, InputStream xsltStream) throws TransformerException, XmlParseException {
    
            Document outputDocument = newDocument();
    
            Document inputDocument;
            if (source instanceof Document) {
                inputDocument = (Document) source;
            } else {
                inputDocument = newDocument();
                Node sourceImported = inputDocument.importNode(source, true);
                inputDocument.appendChild(sourceImported);
            }
    
            Transformer xslt = getTransformerFactory().newTransformer(new StreamSource(xsltStream));
            DOMSource domSource = new DOMSource(inputDocument);
            DOMResult domResult = new DOMResult(outputDocument);
            xslt.transform(domSource, domResult);
    
            if (logger.isDebugEnabled()) {
                logger.debug(xslt.getClass().getName());
                logger.debug("XSLT RESULT: [{}]", serialize(outputDocument));
            }
            return outputDocument;
        }
    
        public Document newDocument() {
            return getDocumentBuilder().newDocument();
        }
    
        private TransformerFactory getTransformerFactory() {
            return this.transformerFactory.get();
        }
    
        private DocumentBuilder getDocumentBuilder() {
            return this.documentBuilder.get();
        }
    }
    

    However it is not possible for me to actually test it because I dont have spring application which you are using so you need to try this by yourself