Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

Building Web Services with CXF

This page describes how to build a CXF web service and use it in Mule.

Mule provides three ways to build a web service:

  1. Use the JAX-WS front end to build a code-first web service employing the standard JAX-WS annotations with the JAXB databinding

  2. Use the JAX-WS front end to build a WSDL-first web service

  3. Use the "simple" front end in CXF to create a web service from simple POJOs

Creating a Code First JAX-WS Service

The JAX-WS specification defines a series of APIs and annotations that help you build web services. This section describes how to create a very simple JAX-WS web service.

You begin by writing the service interface. As the following sample shows, you can write an operation called "sayHi" to greet anyone who submits their name through a web browser:


         
      
1
2
3
4
5
6
7
8
package org.example;
 
import javax.jws.WebService;
 
@WebService
public interface HelloWorld {
    String sayHi(String text);
}

Your implementation of the Web service interface looks like:


         
      
1
2
3
4
5
6
7
8
9
10
11
12
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:


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd">
<http:listener-config name="listener-config" host="localhost" port="63081"/>
<flow name="helloService">
<http:listener config-ref="listener-config" path="hello" />
<cxf:jaxws-service serviceClass="org.example.HelloWorld"/>
<component class="org.example.HelloWorldImpl" />
</flow>
</mule>

Navigate to "http://localhost:63081/hello?wsdl", which displays the WSDL generated by CXF.

To use a POJO instead of an annotated JAX-WS service, use the simple-service CXF feature referencing that POJO as shown in Creating a Simple Front-end Web Service.

Injecting Resources into JAX-WS Services

If you need to access JAX-WS resources, you can have them injected into your service implementation class. Simply add an annotated field such as this:


          
       
1
2
3
4
5
6
@WebService
public class HelloWorldImpl implements HelloWorld {
   
    @Resource
    private WebServiceContext context;
}

To implement injection into your service class, declare it as a Spring bean so that the CXF processor can perform the injection.


          
       
1
2
3
4
5
6
7
8
9
10
11
<spring:bean class="org.apache.cxf.bus.spring.Jsr250BeanPostProcessor" />
<spring:bean id="hello" class="org.example.HelloWorldImpl" />
<http:listener-config name="listener-config" host="localhost" port="63081"/>
 
 <flow name="helloService">
     <http:listener config-ref="listener-config" path="hello" doc:name="HTTP Connector"/> 
    <cxf:jaxws-service serviceClass="org.example.HelloWorld"/>
    <component>
      <spring-object bean="hello" /> 
    </component>
 </flow>

If your component and the injection execute on different threads, limitations in CXF cause the injection to fail. In practical terms, this prevents you from using injection with the following:

  • endpoints that do not use the request-response exchange-pattern.

  • 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 implement WSDL-first services. The CXF distribution includes many additional examples of how to do this.

In general, you begin by generating a web service interface for your WSDL. You can do this using the WSDL to Java tool in CXF or the Maven plugin.

Next, write a service implementation class that implements your service interface, then use this implementation class in the Mule configuration exactly as in the previous example.

Supplying the Original WSDL to CXF

You can specify your original WSDL to CXF by using the @WebService attribute:


          
       
1
2
3
4
@WebService(endpointInterface = "demo.hw.server.HelloWorld",
            serviceName = "HelloWorld",
            wsdlLocation="foo/bar/hello.wsdl")
public class HelloWorldImpl implements HelloWorld

Another approach involves specifying the wsdlLocation property on the endpoint:


          
       
1
<cxf:jaxws-service wsdlLocation="foo/bar/hello.wsdl" />

CXF is able to locate this WSDL inside your webapp, on the classpath, or within the file system.

Creating a Simple Front-End Web Service

A simple front end allows you to create web services which don’t require annotation. First, you write the service interface. As in the example above, you could write an operation called "sayHi" that says "Hello" to anyone who submits their name.


         
      
1
2
3
4
5
package org.example;
 
public interface HelloWorld {
    String sayHi(String text);
}
You can use an implementation class instead of a service interface, although the service interface makes it easier to consume the service. See Consuming Web Services for more information.

Your implementation would then look like this:


         
      
1
2
3
4
5
6
7
8
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:


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd">
<http:listener-config name="listener-config" host="localhost" port="63081"/>
<flow name="helloService">
<http:listener config-ref="listener-config" path="hello" />
<cxf:simple-service serviceClass="org.example.HelloWorld" />
<component class="org.example.HelloWorldImpl" />
</flow>
</mule>

If you go to "http://localhost:63081/hello?wsdl", you see the WSDL that CXF generates.

Advanced Configuration

Validation of Messages

The following code enables schema validation for incoming messages by adding a validationEnabled attribute to your service declaration:


          
       
1
2
3
<simple-service validationEnabled="true"/>
<jaxws-service validationEnabled="true"/>
<proxy-service validationEnabled="true"/>

Changing the Data Binding

You can use the databinding property on an endpoint to configure the databinding to use with that service. The following databinding types are available through CXF:

  1. AegisDatabinding

  2. JAXBDatabinding (Default)

  3. StaxDatabinding

  4. JiBXDatabinding

The following code specifies the databinding class:


          
       
1
2
3
<cxf:simple-service serviceClass="com.acme.MyService">
    <cxf:aegis-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:


          
       
1
<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 as a document) or configure it to send complex types as wrapped instead of literal. To change the message style, set the @SOAPBinding annotation on the service’s interface, specifying the following:

  • style

  • use

  • parameterStyle (optional)

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.


          
       
1
2
3
4
5
6
7
8
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
             use=SOAPBinding.Use.LITERAL,
             parameterStyle=SOAPBinding.ParameterStyle.BARE)
@WebService
public interface Echo
{
    String echo(String src);
}

For more information on the supported message styles, see: Creating Flow Objects and Transformers Using Annotations.