package org.example;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
String sayHi(String text);
}
Building Web Services with CXF
This page describes how to build a CXF web service and use it in Mule.
There are three ways to build a web service.
-
Use the JAX-WS frontend to build a code first web service using the standard JAX-WS annotations with the JAXB databinding
-
Use the JAX-WS frontend to build a WSDL first web service
-
Use the "simple" frontend in CXF to create a web service from simple POJOs
Creating a JAX-WS Service
The JAX-WS specification is a series of APIs and annotations to help you build web services. This section describes how to create a very simple JAX-WS web service.
First, you write the service interface. For example, you could write an operation called "sayHello" that says "Hello" to whoever submits their name.
Your implementation would then look like this:
package org.example;
import javax.jws.WebService;
@WebService(endpointInterface = "org.example.HelloWorld",
serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
return "Hello " + text;
}
}
Configuring the service
To configure Mule to use the service, simply declare your service and use a CXF endpoint as shown in the following example:
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.1/mule.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/3.1/mule-cxf.xsd">
<flow name="helloService">
<http:inbound-endpoint address="http://localhost:63081/hello" exchange-pattern="request-response">
<cxf:jaxws-service serviceClass="org.example.HelloWorld"/>
</http:inbound-endpoint>
<component class="org.example.HelloWorldImpl" />
</flow>
...
If you go to http://localhost:63081/hello?wsdl, you will see the WSDL that CXF generates for you.
If you want to use a POJO instead of creating an annotated JAX-WS service, you could host the POJO as a service component in Mule and use the simple front-end client with its CXF inbound endpoint.
Injecting resources into JAX-WS services
If you need access to JAX-WS resources you can have the injected into your service implementation class. Simply add an annotated field like this:
@WebService
public class HelloWorldImpl implements HelloWorld {
@Resource
private WebServiceContext context;
}
To enable injection into your service class you need to declare it as a Spring bean so that CXF’s processor can perform the injection on it.
<spring:bean class="org.apache.cxf.bus.spring.Jsr250BeanPostProcessor" />
<spring:bean id="hello" class="org.example.HelloWorldImpl" />
<flow name="helloService">
<http:inbound-endpoint address="http://localhost:63081/hello" exchange-pattern="request-response">
<cxf:jaxws-service serviceClass="org.example.HelloWorld"/>
</http:inbound-endpoint>
<component>
<spring-object bean="hello" />
</component>
</flow>
If your component gets executed in a different thread, injection will not work correctly because of limitations in CXF. This means that you cannot use this feature together with endpoints that do not use the request-response exchange-pattern or with the <async/> flow construct.
|
Creating a WSDL First JAX-WS Service
In addition to the code-first approach outlined above, you can also use CXF to do WSDL-first services. While the details are out of the scope of this guide, the CXF distribution includes many examples of how to do this.
First, you generate your web service interface from your WSDL. You can do this using the WSDL to Java tool from CXF.
Next, you write a service implementation class that implements your service interface. You can then use this implementation class in the Mule configuration exactly as in the previous example.
Supplying the Original WSDL to CXF
You can supply your original WSDL to CXF by using the @WebService attribute:
@WebService(endpointInterface = "demo.hw.server.HelloWorld",
serviceName = "HelloWorld",
wsdlLocation="foo/bar/hello.wsdl")
public class HelloWorldImpl implements HelloWorld
Another way is to specify the wsdlLocation property on the endpoint:
<cxf:jaxws-service address="http://localhost:63081/hello" wsdlLocation="foo/bar/hello.wsdl" />
CXF is able to locate this WSDL inside your webapp, on the classpath, or on the file system.
Creating a simple frontend web service
The simple frontend allows you to create web services which don’t require any annotations. First, you write the service interface. As in the example above, you could write an operation called "sayHello" that says "Hello" to whoever submits their name.
You don’t have to use a service interface, you can just use an implementation class. However, the service interface makes it possible to consume the service very easily. See Consuming Web Services for more information. |
package org.example;
public interface HelloWorld {
String sayHi(String text);
}
Your implementation would then look like this:
package org.example;
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
return "Hello " + text;
}
}
Configuring the service
To configure Mule to use the service, simply declare your service and use a CXF message processor as shown in the following example:
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.1/mule.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/3.1/mule-cxf.xsd">
<flow name="helloService">
<http:inbound-endpoint address="http://localhost:63081/hello" exchange-pattern="request-response">
<cxf:simple-service serviceClass="org.example.HelloWorld"/>
</http:inbound-endpoint>
<component class="org.example.HelloWorldImpl" />
</flow>
...
If you go to http://localhost:63081/hello?wsdl, you will see the WSDL that CXF generates for you.
Advanced Configuration
Validation of Messages
To enable schema validation for incoming messages add a validationEnabled attribute to your service declation. For example:
<simple-service validationEnabled="true"/>
<jaxws-service validationEnabled="true"/>
<proxy-service validationEnabled="true"/>
Changing the Data Binding
You can use the data-binding property on an endpoint to configure the data binding to use with that service. Following are the types of data bindings available with CXF:
-
AegisDatabinding
-
JAXBDatabinding (Default)
-
StaxDatabinding
You specify the data-binding class to use as follows:
<cxf:simple-service serviceClass="com.acme.MyService">
<cxf:databinding>
<spring:bean class="org.apache.cxf.aegis.databinding.AegisDatabinding"/>
</cxf:databinding>
</cxf:simple-service>
The <cxf:databinding> element can be used with any CXF front-end.
Setting the Binding URI
The bindingUri attribute specifies how your service operations are mapped to resources. You configure this attribute as follows:
<cxf:jaxws-service serviceClass="com.acme.MyService" bindingUri="http://www.w3.org/2003/05/soap/bindings/HTTP/" />
Changing the Default Message Style
By default, CXF uses the Document/Literal message style. However, you can change the service to be exposed as RPC instead of document or to send complex types as wrapped instead of literal. To change the message style, you set the @SOAPBinding annotation on the service’s interface, specifying the style, use, and optionally the parameterStyle.
In the following example, the parameter style is set to BARE. This means that each parameter is placed into the message body as a child element of the message root. This is WRAPPED by default.
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.BARE)
@WebService
public interface Echo
{
String echo(String src);
}