[
https://issues.apache.org/jira/browse/CAMEL-11927?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16235895#comment-16235895
]
ASF GitHub Bot commented on CAMEL-11927:
----------------------------------------
onders86 closed pull request #2055: CAMEL-11927 - Improve support for soap
header transformations - [Than…
URL: https://github.com/apache/camel/pull/2055
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/components/camel-spring-ws/src/main/docs/spring-ws-component.adoc
b/components/camel-spring-ws/src/main/docs/spring-ws-component.adoc
index 96184457773..d918008847f 100644
--- a/components/camel-spring-ws/src/main/docs/spring-ws-component.adoc
+++ b/components/camel-spring-ws/src/main/docs/spring-ws-component.adoc
@@ -163,10 +163,10 @@ the message.
|`CamelSpringWebserviceAddressingAction` |URI |Use this header to specify the
WS-Addressing action of the message,
overrides `wsAddressingAction` option if present
-|CamelSpringWebserviceAddressingFaultTo |URI |Use this header to specify the
WS-Addressing FaultTo , overrides
+|CamelSpringWebserviceAddressingFaultTo |URI |Use this header to specify the
WS-Addressing FaultTo , overrides
faultTo option if present
-|CamelSpringWebserviceAddressingReplyTo |URI |Use this header to specify the
WS-Addressing ReplyTo , overrides
+|CamelSpringWebserviceAddressingReplyTo |URI |Use this header to specify the
WS-Addressing ReplyTo , overrides
replyTo option if present
|CamelSpringWebserviceAddressingOutputAction |URI |Use this header to specify
the WS-Addressing Action , overrides
@@ -250,10 +250,10 @@ test].
### The header and attachment propagation
Spring WS Camel supports propagation of the headers and attachments into
-Spring-WS WebServiceMessage response since version *2.10.3*. The
+Spring-WS WebServiceMessage response since version *2.10.3*. The
endpoint will use so called "hook" the MessageFilter (default
implementation is provided by BasicMessageFilter) to propagate the
-exchange headers and attachments into WebServiceMessage response. Now
+exchange headers and attachments into WebServiceMessage response. Now
you can use
[source,java]
@@ -266,6 +266,28 @@ Note: If the exchange header in the pipeline contains
text, it generates
Qname(key)=value attribute in the soap header. Recommended is to create
a QName class directly and put into any key into header.
+### How to transform the soap header using a stylesheet
+The header transformation filter (HeaderTransformationMessageFilter.java)
+can be used to transform the soap header for a soap request. If you want to
use
+the header transformation filter, see the below example:
+
+[source,java]
+------------------------------------------------------------------
+<bean id="headerTransformationFilter"
class="org.apache.camel.component.spring.ws.filter.impl.HeaderTransformationMessageFilter">
+ <constructor-arg index="0"
value="org/apache/camel/component/spring/ws/soap-header-transform.xslt"/>
+</bean
+------------------------------------------------------------------
+Use the bead defined above in the camel endpoint
+
+[source,java]
+------------------------------------------------------------------
+<route>
+ <from uri="direct:stockQuoteWebserviceHeaderTransformation"/>
+ <to
uri="spring-ws:http://localhost?webServiceTemplate=#webServiceTemplate&soapAction=http://www.stockquotes.edu/GetQuote&messageFilter=#headerTransformationFilter"/>
+</route>
+------------------------------------------------------------------
+
+
### How to use MTOM attachments
The BasicMessageFilter provides all required information for Apache
@@ -576,4 +598,4 @@
from("spring-ws:rootqname:{http://example.com/}GetFoo?endpointMapping=#endpointM
* link:configuring-camel.html[Configuring Camel]
* link:component.html[Component]
* link:endpoint.html[Endpoint]
-* link:getting-started.html[Getting Started]
+* link:getting-started.html[Getting Started]
\ No newline at end of file
diff --git
a/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/CompositeMessageFilter.java
b/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/CompositeMessageFilter.java
new file mode 100644
index 00000000000..c291e4bf40a
--- /dev/null
+++
b/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/CompositeMessageFilter.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.spring.ws.filter.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.spring.ws.filter.MessageFilter;
+import org.springframework.ws.WebServiceMessage;
+
+/**
+ * This filter is a composition of basic message filters
+ */
+public class CompositeMessageFilter implements MessageFilter {
+
+ private List<MessageFilter> filters = new ArrayList<>();
+
+ @Override
+ public void filterProducer(Exchange exchange, WebServiceMessage response) {
+ for (MessageFilter filter : filters) {
+ filter.filterProducer(exchange, response);
+ }
+ }
+
+ @Override
+ public void filterConsumer(Exchange exchange, WebServiceMessage response) {
+ for (MessageFilter filter : filters) {
+ filter.filterConsumer(exchange, response);
+ }
+ }
+
+ public void setFilters(List<MessageFilter> filters) {
+ this.filters = filters;
+ }
+
+ public List<MessageFilter> getFilters() {
+ return filters;
+ }
+}
diff --git
a/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/HeaderTransformationMessageFilter.java
b/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/HeaderTransformationMessageFilter.java
new file mode 100644
index 00000000000..10bbb33f39d
--- /dev/null
+++
b/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/HeaderTransformationMessageFilter.java
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.spring.ws.filter.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.xml.XsltUriResolver;
+import org.apache.camel.component.spring.ws.filter.MessageFilter;
+import org.apache.camel.component.xslt.XsltComponent;
+import org.apache.camel.component.xslt.XsltEndpoint;
+import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.soap.SoapMessage;
+
+/**
+ * Message filter that transforms the header of a soap message
+ */
+public class HeaderTransformationMessageFilter implements MessageFilter {
+ private static final String SOAP_HEADER_TRANSFORMATION_PROBLEM = "Soap
header transformation problem";
+ private static final Logger LOG =
LoggerFactory.getLogger(HeaderTransformationMessageFilter.class);
+ private String xslt;
+ private boolean saxon;
+
+ /**
+ * @param xslt
+ */
+ public HeaderTransformationMessageFilter(String xslt) {
+ super();
+ this.xslt = xslt;
+ }
+
+ @Override
+ public void filterProducer(Exchange exchange, WebServiceMessage
webServiceMessage) {
+ if (exchange != null) {
+ processHeader(exchange.getContext(), exchange.getIn(),
webServiceMessage);
+ }
+ }
+
+ @Override
+ public void filterConsumer(Exchange exchange, WebServiceMessage
webServiceMessage) {
+ if (exchange != null) {
+ Message responseMessage = exchange.hasOut() ? exchange.getOut() :
exchange.getIn();
+ processHeader(exchange.getContext(), responseMessage,
webServiceMessage);
+ }
+ }
+
+ /**
+ * Transform the header
+ * @param context
+ * @param inOrOut
+ * @param webServiceMessage
+ */
+ private void processHeader(CamelContext context, Message inOrOut,
WebServiceMessage webServiceMessage) {
+ if (webServiceMessage instanceof SoapMessage) {
+ SoapMessage soapMessage = (SoapMessage) webServiceMessage;
+ try {
+ XsltUriResolver resolver = new XsltUriResolver(context, xslt);
+ Source stylesheetResource = resolver.resolve(xslt, null);
+
+ TransformerFactory transformerFactory =
getTransformerFactory(context);
+ Transformer transformer =
transformerFactory.newTransformer(stylesheetResource);
+
+ addParameters(inOrOut, transformer);
+
+ transformer.transform(soapMessage.getSoapHeader().getSource(),
soapMessage.getSoapHeader().getResult());
+ } catch (TransformerException e) {
+ throw new RuntimeException("Cannot transform the header of the
soap message", e);
+ }
+ }
+ }
+
+ /**
+ * Adding the headers of the message as parameter to the transformer
+ *
+ * @param inOrOut
+ * @param transformer
+ */
+ private void addParameters(Message inOrOut, Transformer transformer) {
+ Map<String, Object> headers = inOrOut.getHeaders();
+ for (Map.Entry<String, Object> headerEntry : headers.entrySet()) {
+ String key = headerEntry.getKey();
+
+ // Key's with '$' are not allowed in XSLT
+ if (key != null && !key.startsWith("$")) {
+ transformer.setParameter(key,
String.valueOf(headerEntry.getValue()));
+ }
+ }
+ }
+
+ /**
+ * Getting a {@link TransformerFactory} with logging
+ *
+ * @return {@link TransformerFactory}
+ */
+ private TransformerFactory getTransformerFactory(CamelContext context) {
+ TransformerFactory transformerFactory = null;
+ if (saxon) {
+ transformerFactory = getSaxonTransformerFactory(context);
+ } else {
+ transformerFactory = TransformerFactory.newInstance();
+ }
+
+ if (transformerFactory == null) {
+ throw new IllegalStateException("Cannot resolve a transformer
factory");
+ }
+
+ transformerFactory.setErrorListener(new ErrorListener() {
+
+ @Override
+ public void warning(TransformerException exception) throws
TransformerException {
+ LOG.warn(SOAP_HEADER_TRANSFORMATION_PROBLEM, exception);
+ }
+
+ @Override
+ public void fatalError(TransformerException exception) throws
TransformerException {
+ LOG.error(SOAP_HEADER_TRANSFORMATION_PROBLEM, exception);
+ }
+
+ @Override
+ public void error(TransformerException exception) throws
TransformerException {
+ LOG.error(SOAP_HEADER_TRANSFORMATION_PROBLEM, exception);
+ }
+ });
+
+ return transformerFactory;
+ }
+
+ /**
+ * Loading the saxon transformer class
+ *
+ * @param context
+ * @return
+ */
+ private TransformerFactory getSaxonTransformerFactory(CamelContext
context) {
+ final ClassResolver resolver = context.getClassResolver();
+ try {
+ Class<TransformerFactory> factoryClass =
resolver.resolveMandatoryClass(
+ XsltEndpoint.SAXON_TRANSFORMER_FACTORY_CLASS_NAME,
TransformerFactory.class,
+ XsltComponent.class.getClassLoader());
+
+ if (factoryClass != null) {
+ return ObjectHelper.newInstance(factoryClass);
+ }
+
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Cannot load the saxon transformer
class", e);
+ }
+
+ return null;
+ }
+
+ public String getXslt() {
+ return xslt;
+ }
+
+ public void setXslt(String xslt) {
+ this.xslt = xslt;
+ }
+
+ public boolean isSaxon() {
+ return saxon;
+ }
+
+ public void setSaxon(boolean saxon) {
+ this.saxon = saxon;
+ }
+
+}
\ No newline at end of file
diff --git
a/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/SoapHeaderTest-context.xml
b/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/SoapHeaderTest-context.xml
index 44949112b9a..d707910455b 100644
---
a/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/SoapHeaderTest-context.xml
+++
b/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/SoapHeaderTest-context.xml
@@ -29,6 +29,11 @@
<from uri="direct:stockQuoteWebservice"/>
<to
uri="spring-ws:http://localhost?webServiceTemplate=#webServiceTemplate&soapAction=http://www.stockquotes.edu/GetQuote"/>
</route>
+
+ <route>
+ <from uri="direct:stockQuoteWebserviceHeaderTransformation"/>
+ <to
uri="spring-ws:http://localhost?webServiceTemplate=#webServiceTemplate&soapAction=http://www.stockquotes.edu/GetQuote&messageFilter=#headerTransformationFilter"/>
+ </route>
<!-- consumer route (providing the actual web service) that responds
with the request so we can see SOAP headers -->
<route>
@@ -51,5 +56,9 @@
<bean
class="net.javacrumbs.springws.test.helper.InMemoryWebServiceMessageSender"/>
</property>
</bean>
+
+ <bean id="headerTransformationFilter"
class="org.apache.camel.component.spring.ws.filter.impl.HeaderTransformationMessageFilter">
+ <constructor-arg index="0"
value="org/apache/camel/component/spring/ws/soap-header-transform.xslt"/>
+ </bean>
</beans>
\ No newline at end of file
diff --git
a/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/soap-header-transform.xslt
b/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/soap-header-transform.xslt
new file mode 100644
index 00000000000..06ad8cb6fa5
--- /dev/null
+++
b/components/camel-spring-ws/src/test/resources/org/apache/camel/component/spring/ws/soap-header-transform.xslt
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://www.webserviceX.NET/">
+ <xsl:strip-space elements="*"/>
+ <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
+
+ <!-- copy everything else -->
+ <xsl:template match="node()|@*">
+ <xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates select="node()"/>
+ </xsl:copy>
+ </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> camel-spring-ws - Support for header transformation
> ---------------------------------------------------
>
> Key: CAMEL-11927
> URL: https://issues.apache.org/jira/browse/CAMEL-11927
> Project: Camel
> Issue Type: Improvement
> Components: camel-spring-ws
> Affects Versions: 2.19.3
> Reporter: Richard Groote
> Assignee: Önder Sezgin
> Priority: Major
> Fix For: 2.21.0
>
> Attachments: CompositeMessageFilter.java,
> HeaderTransformationMessageFilter.java, SoapHeaderTest-context.xml,
> SoapHeaderTest.java, soap-header-transform.xslt, spring-ws-component.adoc
>
>
> Improve support for soap header transformations:
> - The composite message filter is to have multiple filters applied
> - Header transformation filters is use to transform the soap header using a
> stylesheet.
> I was not able to create a pull request for it
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)