Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

JAX-RS relies on MessageBodyReader and MessageBodyWriter implementations to serialize and de-serialize Java types. JAX-RS requires that certain types has to be supported out of the box.
By default, CXF supports String, byte[], InputStream, Reader, File, JAXP Source, JAX-RS StreamingOutput, JAXB-annotated types with application/xml and application/json formats as well as JAXBElement (see below). JAX-RS MultivaluedMap is also supported for
form contents. Support for other types like Reader and StreamingOutput is on the way.

Custom Message Body Providers

...

Code Block
java
java

@ProduceMime("text/plain")
@Provider
public class LongProvider implements MessageBodyWriter<Long> {

    public long getSize(Long l) {
        return -1;
    }

    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations) {
        return long.class.isAssignableFrom(type) || Long.class.isAssignableFrom(type);
    }

    public void writeTo(Long l, Class<?> clazz, Type type, Annotation[] a, 
                        MediaType mt, MultivaluedMap<String, Object> headers, OutputStream os) 
        throws IOException {
        os.write(l.toString().getBytes());
        
    }

CXF ships some custom providers too. These are providers for dealing with Atom (based on Apache Abdera) and XMLObjects.
CXF also supports primitive types and their Number friends when text/plain media type is used, either on input or output.

Registering custom providers

Putting @Provider annotation on the provider class is something that should lead to your provider being registered with the runtime. CXF does not support this feature yet.

One can easily register a provider either from the Spring configuration or programmatically :

Code Block
xml
xml

<beans>
<jaxrs:server id="customerService" address="/">
    <jaxrs:serviceBeans>
      <bean class="org.CustomerService" />
    </jaxrs:serviceBeans>

    <jaxrs:entityProviders>providers>
      <bean ref="isProvider" />
      <bean ref="longProvider" />
    </jaxrs:entityProviders>providers>
    <bean id="isProvider" class="com.bar.providers.InputStreamProvider"/>
    <bean id="longProvider" class="com.bar.providers.LongProvider"/>
</jaxrs:server>
</beans>

Please note that once CXF is updated to support a 0.7 version of JAX-RS api, <jaxrs:entityProviders> will be changed to Note that instead of the older <jaxrs:entityProviders> it's now <jaxrs:providers>. JAX-RS supports different types of providers and having a single <jaxrs:providers> container is in line with the way other JAX-RS implementations discover providers by checking for @Provider annotations only.

See below a more complete beans.xml definition.

Content type negotiation

One of the coolest thing of REST is that the same resource can be served using multiple representations. @ProduceMime and @ConsumeMime annotations are used to declare the supported request and response media types.

While having @Provider-annotated providers automatically registered is a handy feature indeed, sometimes it might actually be problematic.
For ex, in a large project user providers from different libraries might clash. Also, with a custom configuration (as shown above) a different type of provider (handling the same format of request/response bodies) can be registered with a different jaxrs:server instance.

Content type negotiation

One of the coolest thing of REST is that the same resource can be served using multiple representations. @ProduceMime and @ConsumeMime annotations are used to declare the supported request and response media types.

JAXB JAXB support

The request and response can be marshaled marshalled and unmarshaled unmarshalled to/from Java object using JAXB. The Java object needs to be marked

There's a number of ways to tell to the JAXB provider how objects can be serialized. The simplest way is to mark a given type with @XmlRootElement annotation.

For example:

Code Block
java
java
@XmlRootElement(name = "Customer")
public class Customer {
    private String name;
    private long id;

    public Customer() {
    }

    public void setName(String n) {
        name = n;
    }

    public String getName() {
        return name;
    }

    public void setId(long i) {
        id = i;
    }

    public long getId() {
        return id;
    }

}

In the example below, the Customer object returned by getCustomer is marshaled using JAXB data binding:

...

Code Block
java
java
@Path("/customerservice/")
<Customer>
    <id>123</id>
    <name>John</name>
</Customer>

To The simplest way to work with the collections , you need is to define an object collection typea type representing a collection. For example:

Code Block
@XmlRootElement(name = "Customers")
public class Customers {
    private Collection<Customer> customers;

    public Collection<Customer> getCustomer() {
        return customers;
    }

    public void setCustomer(Collection<Customer> c) {
        this.customers = c;
    }
}
@Path("/customerservice/")
public class CustomerService {
    @GET
    @Path("/customers/")
    public Customers getCustomers() {
        ....
    }
}

JSON support

Following code returns a Customer object that is marshaled to JSON format:

Alternatively to using @XmlRootElement and Collection wrappers, one can provide an Object factory which will tell JAXB how to
marshal a given type (in case of Collections - its template type). Another option is to return/accept a JAXBElement directly from/in
a given method.

Finally, JAXBProvider provides an experimental support for marshalling response types of methods annotated with @XmlJavaTypeAdapter annotations.
It's likely that at some point of time JAX-RS runtime will be capable of automatically generating such adapters.

JSON support

Default JSON provider relies on Jettison 1.0.1 and it expects the types it deals with to follow the same techniques as described above
in the JAXB support section for them to be handled properly.

Following code returns a Customer object that is marshaled to JSON format:

Code Block

@Path("/customerservice/")
public class CustomerService {
    @ProduceMime("application/json")
    @GET
    @Path("/customers/{customerId}/")
    public Customer getCustomer(@PathParam("customerId") String id) {
        ....
    }

The wire representation of Customer object is:

Code Block
java
java

{"Customer ":{"id":"123","name":"john"}}

Source support

You can also receive the request as a Source object or return a Source object as response:

Code Block
java
java

@Path("/customerservice/")
public class CustomerService {
    @PUT
    @Path("/customers/")
    public javax.xml.transform.Source updateCustomer(javax.xml.transform.Source ds) {
        ....
    }
}

Debugging

One can easily try from a browser how a given resource class reacts to different HTTP Accept or Accept-Language header values.
For example, if a resource class supports "/resource" URI then one can test the resource class using one of the following
queries :

GET /resource.xml
GET /resource.en

The runtime will replace '.xml' or '.en' with an appropriate header value. For it to know the type or language value associated with
a given URI suffix, some configuration needs to be done. Here's an example how to do it in Spring :

Code Block
xml
xml


  <jaxrs:server id="customerService" address="/">
    <jaxrs:serviceBeans>
      <ref bean="customerService" />
    </jaxrs:serviceBeans>
    <jaxrs:extensionMappings>
      <entry key="json" value="application/json"/>
      <entry key="xml" value="application/xml"/>
    </jaxrs:extensionMappings>
    <jaxrs:languageMappings/>
  </jaxrs:server>

See below for a more complete configuration example.

See the JAX-RS specification for more details.

CXF also supports _type query as an alternative to appending extensions like '.xml' to request URIs :

GET /resource?_type=xml

Filters

CXF suports filters. Often it's necessary to pre- or post-process some requests according to a number of requirements.
For example, a request like

GET /resource?_type=xml is supported by a CXF specific RequestHandler filter which modifices the CXF input Message
by updating one of its headers.

In some cases users can use the existing filter technologies such as Servler filters or Spring AOP proxies. In other cases, it can be handy
to write a CXF filter which will introspect the resource class, input or output message, the operation which was invoked and modify the request or response accordingly.

Note that the corresponding interfaces will most likely change in the short term. Here they are anyway, the implementations can be registered like any other types of providers.

Code Block
java
java

public interface RequestHandler {
    
    Response handleRequest(Message inputMessage, 
                
Code Block

@Path("/customerservice/")
public class CustomerService {
    @ProduceMime("application/json")
    @GET
    @Path("/customers/{customerId}/")
    public Customer getCustomer(@PathParam("customerId") String id) {
        ....
    }

The wire representation of Customer object is:

...


{"Customer ":{"id":"123","name":"john"}}
ClassResourceInfo resourceClass);

}

The request handler implementation can either modify the input Message and let the request to proceed or block the request
by returning a non-null Response.

Source support

You can also receive the request as a Source object or return a Source object as response:

Code Block
java
java
@Path("/customerservice/")
public class CustomerService {public interface ResponseHandler {
    
    Response handleResponse(Message outputMessage,
                           OperationResourceInfo invokedOperation, 
    @PUT
    @Path("/customers/")
    public javax.xml.transform.Source updateCustomer(javax.xml.transform.Source ds) {
        ....
   Response }response);

}

...

The response handler implementation can optionally overwrite or modify the application Response.
Multiple request and response handlers are supported.

Advanced HTTP

CXF provides a partial support for an advanced content type negotiation by handling If-Match headers and ETags in its JAX-RS Request implementation. Neither If-Modified-Since nor Vary headers are currently supported.

It also supports CacheControl and Cookies.

Secure JAX-RS services

A demo called samples\jax_rs\basic_https shows you how to do communications using HTTPS.

...