Since we're on a major migration process of this website, some component documents here are out of sync right now. In the meantime you may want to look at the early version of the new website
https://camel.apache.org/staging/
We would very much like to receive any feedback on the new site, please join the discussion on the Camel user mailing list.
Spring Web Services ComponentAvailable as of Camel 2.6 The spring-ws: component allows you to integrate with Spring Web Services. It offers both client-side support, for accessing web services, and server-side support for creating your own contract-first web services. Maven users will need to add the following dependency to their <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring-ws</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency> Dependencies As of Camel 2.8 this component ships with Spring-WS 2.0.x which (like the rest of Camel) requires Spring 3.0.x. Earlier Camel versions shipped Spring-WS 1.5.9 which is compatible with Spring 2.5.x and 3.0.x. In order to run earlier versions of URI formatThe URI scheme for this component is as follows spring-ws:[mapping-type:]address[?options] To expose a web service mapping-type needs to be set to any of the following:
As a consumer the address should contain a value relevant to the specified mapping-type (e.g. a SOAP action, XPath expression). As a producer the address should be set to the URI of the web service your calling upon. You can append query options to the URI in the following format, Options
Message headers
Accessing web servicesTo call a web service at from("direct:example").to("spring-ws:http://foo.com/bar") And sent a message: template.requestBody("direct:example", "<foobar xmlns=\"http://foo.com\"><msg>test message</msg></foobar>"); Remember if it's a SOAP service you're calling you don't have to include SOAP tags. Spring-WS will perform the XML-to-SOAP marshaling. Sending SOAP and WS-Addressing action headersWhen a remote web service requires a SOAP action or use of the WS-Addressing standard you define your route as: from("direct:example") .to("spring-ws:http://foo.com/bar?soapAction=http://foo.com&wsAddressingAction=http://bar.com") Optionally you can override the endpoint options with header values: template.requestBodyAndHeader("direct:example", "<foobar xmlns=\"http://foo.com\"><msg>test message</msg></foobar>", SpringWebserviceConstants.SPRING_WS_SOAP_ACTION, "http://baz.com"); Using SOAP headersAvailable as of Camel 2.11.1 You can provide the SOAP header(s) as a Camel Message header when sending a message to a spring-ws endpoint, for example given the following SOAP header in a String String body = ... String soapHeader = "<h:Header xmlns:h=\"http://www.webserviceX.NET/\"><h:MessageID>1234567890</h:MessageID><h:Nested><h:NestedID>1111</h:NestedID></h:Nested></h:Header>"; We can set the body and header on the Camel Message as follows: exchange.getIn().setBody(body); exchange.getIn().setHeader(SpringWebserviceConstants.SPRING_WS_SOAP_HEADER, soapHeader); And then send the Exchange to a Likewise the spring-ws consumer will also enrich the Camel Message with the SOAP header. For an example see this unit test. The header and attachment propagationSpring WS Camel supports propagation of the headers and attachments into 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 you can use exchange.getOut().getHeaders().put("myCustom","myHeaderValue") exchange.getIn().addAttachment("myAttachment", new DataHandler(...)) 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 use MTOM attachmentsThe BasicMessageFilter provides all required information for Apache Axiom in order to produce MTOM message. If you want to use Apache Camel Spring WS within Apache Axiom, here is an example: <bean id="axiomMessageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory"> <property name="payloadCaching" value="false" /> <property name="attachmentCaching" value="true" /> <property name="attachmentCacheThreshold" value="1024" /> </bean> 2. Add into your pom.xml the following dependencies <dependency> <groupId>org.apache.ws.commons.axiom</groupId> <artifactId>axiom-api</artifactId> <version>1.2.13</version> </dependency> <dependency> <groupId>org.apache.ws.commons.axiom</groupId> <artifactId>axiom-impl</artifactId> <version>1.2.13</version> <scope>runtime</scope> </dependency> 3. Add your attachment into the pipeline, for example using a Processor implementation. private class Attachement implements Processor { public void process(Exchange exchange) throws Exception { exchange.getOut().copyFrom(exchange.getIn()); File file = new File("testAttachment.txt"); exchange.getOut().addAttachment("test", new DataHandler(new FileDataSource(file))); } } 4. Define endpoint (producer) as ussual, for example like this: from("direct:send") .process(new Attachement()) .to("spring-ws:http://localhost:8089/mySoapService?soapAction=mySoap&messageFactory=axiomMessageFactory"); 5. Now, your producer will generate MTOM message with otpmized attachments. The custom header and attachment filteringIf you need to provide your custom processing of either headers or attachments, extend existing BasicMessageFilter and override the appropriate methods or write a brand new implementation of the MessageFilter interface. You can specify either a global a or a local message filter as follows: <bean id="messageFilter" class="your.domain.myMessageFiler" scope="singleton" /> or to("spring-ws:http://yourdomain.com?messageFilter=#myEndpointSpecificMessageFilter"); For more information see CAMEL-5724 If you want to create your own MessageFilter, consider overriding the following methods in the default implementation of MessageFilter in class BasicMessageFilter: protected void doProcessSoapHeader(Message inOrOut, SoapMessage soapMessage) {your code /*no need to call super*/ } protected void doProcessSoapAttachements(Message inOrOut, SoapMessage response) { your code /*no need to call super*/ } Using a custom MessageSender and MessageFactoryA custom message sender or factory in the registry can be referenced like this: from("direct:example") .to("spring-ws:http://foo.com/bar?messageFactory=#messageFactory&messageSender=#messageSender") Spring configuration: <!-- authenticate using HTTP Basic Authentication --> <bean id="messageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender"> <property name="credentials"> <bean class="org.apache.commons.httpclient.UsernamePasswordCredentials"> <constructor-arg index="0" value="admin"/> <constructor-arg index="1" value="secret"/> </bean> </property> </bean> <!-- force use of Sun SAAJ implementation, http://static.springsource.org/spring-ws/sites/1.5/faq.html#saaj-jboss --> <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"> <property name="messageFactory"> <bean class="com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl"></bean> </property> </bean> Exposing web servicesIn order to expose a web service using this component you first need to set-up a MessageDispatcher to look for endpoint mappings in a Spring XML file. If you plan on running inside a servlet container you probably want to use a By default the web.xml <web-app> <servlet> <servlet-name>spring-ws</servlet-name> <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring-ws</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app> spring-ws-servlet.xml <bean id="endpointMapping" class="org.apache.camel.component.spring.ws.bean.CamelEndpointMapping" /> <bean id="wsdl" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition"> <property name="schema"> <bean class="org.springframework.xml.xsd.SimpleXsdSchema"> <property name="xsd" value="/WEB-INF/foobar.xsd"/> </bean> </property> <property name="portTypeName" value="FooBar"/> <property name="locationUri" value="/"/> <property name="targetNamespace" value="http://example.com/"/> </bean> More information on setting up Spring-WS can be found in Writing Contract-First Web Services. Basically paragraph 3.6 "Implementing the Endpoint" is handled by this component (specifically paragraph 3.6.2 "Routing the Message to the Endpoint" is where Endpoint mapping in routesWith the XML configuration in-place you can now use Camel's DSL to define what web service requests are handled by your endpoint: The following route will receive all web service requests that have a root element named "GetFoo" within the from("spring-ws:rootqname:{http://example.com/}GetFoo?endpointMapping=#endpointMapping") .convertBodyTo(String.class).to(mock:example) The following route will receive web service requests containing the from("spring-ws:soapaction:http://example.com/GetFoo?endpointMapping=#endpointMapping") .convertBodyTo(String.class).to(mock:example) The following route will receive all requests sent to from("spring-ws:uri:http://example.com/foobar?endpointMapping=#endpointMapping") .convertBodyTo(String.class).to(mock:example) The route below will receive requests that contain the element from("spring-ws:xpathresult:abc?expression=//foobar&endpointMapping=#endpointMapping") .convertBodyTo(String.class).to(mock:example) Alternative configuration, using existing endpoint mappingsFor every endpoint with mapping-type The use of the An example of a route using <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="spring-ws:beanname:QuoteEndpointDispatcher" /> <to uri="mock:example" /> </route> </camelContext> <bean id="legacyEndpointMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping"> <property name="mappings"> <props> <prop key="{http://example.com/}GetFuture">FutureEndpointDispatcher</prop> <prop key="{http://example.com/}GetQuote">QuoteEndpointDispatcher</prop> </props> </property> </bean> <bean id="QuoteEndpointDispatcher" class="org.apache.camel.component.spring.ws.bean.CamelEndpointDispatcher" /> <bean id="FutureEndpointDispatcher" class="org.apache.camel.component.spring.ws.bean.CamelEndpointDispatcher" /> POJO (un)marshallingCamel's pluggable data formats offer support for pojo/xml marshalling using libraries such as JAXB, XStream, JibX, Castor and XMLBeans. You can use these data formats in your route to sent and receive pojo's, to and from web services. When accessing web services you can marshal the request and unmarshal the response message: JaxbDataFormat jaxb = new JaxbDataFormat(false); jaxb.setContextPath("com.example.model"); from("direct:example").marshal(jaxb).to("spring-ws:http://foo.com/bar").unmarshal(jaxb); Similarly when providing web services, you can unmarshal XML requests to POJO's and marshal the response message back to XML: from("spring-ws:rootqname:{http://example.com/}GetFoo?endpointMapping=#endpointMapping").unmarshal(jaxb) .to("mock:example").marshal(jaxb); |