Versions Compared

Key

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

CXF has an initial implementation of JAX-RS (JSR-311): Java API for RESTfulWeb Services. JAX-RS provides a more standard way to build RESTful services in Java. 0.6 8 version of JSR-311 API is currently supported.

JAX-RS related demos are located under samples\jax_rs directory (CXF 2.1 only).

...

A resource class is a Java Class class annotated with JAX-RS annotations to represent a Web resource. A typical resource class in JAX-RS looks like this below:

...

@Path annotation is applied to resource classes or methods. The value of @Path annotation is a relative URI path and follows the URI Template format.

...

Code Block
java
java
@Path("/customerservice/")
public class CustomerService {

    
    @PUT
    @Path("/customers/{id}")
    public Response updateCustomer(@PathParam("id") Long id, Customer customer) {
        return Response.status(errorCode).build();
    }

    @POST
    @Path("/customers")
    public Customer addCustomer(Customer customer) {
        throw new WebApplicationException(errorCode);
    }

}

Dealing with Parameters

PathParam annotation is used to map a given Path template variable to a method parameter.
For example Yet another option is to register an ExceptionMapper provider. Ex :

Code Block
java
java


@Path("/customer/{id}")
public BookExceptionMapper classimplements CustomerServiceExceptionMapper<BookException> {

    
public Response toResponse(BookException ex) @PUT{
    @Path("{name}")
    // convert publicto Response updateCustomer(@PathParam("id") Long id, @PathParam("name") String name) {
        ...
    
    }
}

In this case a template variable id available from a root class annotation is mapped to a parameter of type Long, while a name variable is mapped to a parameter of type String.
Paramaters can be of type String or of any type that have constructors accepting a String argument or static valueOf(String s) methods. JAX-RS PathSegment is also supported.

QueryParam, HttpHeader and CookieParam annotations are also supported.

Context annotations

If a parameter or field of either UriInfo or HttpHeaders or SecurityContext or one of the Servlet types like ServeltContext or MessageBodyWorkers is annotated with a Context annotation then CXF will provide properly initialized instances to the application code.

Note that if fields are annotated with Context then care should be taken for singleton resource classes as CXF does not support yet a thread-local injection of Context fields.

Injection of contexts into message body providers is not supported yet.

Example :

This allows to throw exceptions from an application code and deal with the proper mappping to an HTTP response in a registered provider.

Dealing with Parameters

PathParam annotation is used to map a given Path template variable to a method parameter.
For example :

Code Block
java
java


@Path("/customer/{id}")
public class CustomerService {

    
    @PUT
    @Path("{name}")
    public Response updateCustomer(@PathParam("id") Long id, @PathParam("name") String name) {
        ...
    }
}

In this case a template variable id available from a root class annotation is mapped to a parameter of type Long, while a name variable is mapped to a parameter of type String.
Paramaters can be of type String or of any type that have constructors accepting a String argument or static valueOf(String s) methods. JAX-RS PathSegment is also supported.

QueryParam, HttpHeader and CookieParam annotations are also supported.

Context annotations

If a parameter or field of either UriInfo or HttpHeaders or SecurityContext or one of the Servlet types like ServeltContext or MessageBodyWorkers is annotated with a Context annotation then CXF will provide properly initialized instances to the application code.

Note that if fields are annotated with Context then care should be taken for singleton resource classes as CXF does not support yet a thread-local injection of Context fields.

Injection of contexts into message body providers is not supported yet.

Example :

Code Block
java
java

@Path("/customer")
public class CustomerService {
    
    @Context ServletContext sc;
    @Context SecurityContext sc;
    
    @PUT
    public Response updateCustomer(@Context UriInfo u, @Context HttpHeader h, Customer c) {
        ...
    }
}

Annotation inheritance

Most of the JAX-RS annotations can be inherited from either an interface or a superclass. JAX-RS specification requires that only the ones applied to methods can be inherited. For example :

Code Block
java
java


public interface CustomerService {

    @PUT
    @Path("/customers/{id}")
    Response updateCustomer(@PathParam("id") Long id, Customer customer) {
        return Response.status(errorCode).build();
    }

    @POST
    @Path("/customers")
    Customer addCustomer(Customer customer) {
        throw new WebApplicationException(errorCode);
    }

}

@Path("/customerservice/")
public class Customers implements CustomerService {

    
    public Response updateCustomer(Long id, Customer customer) {
        return Response.status(errorCode).build();
    }

    public Customer addCustomer(Customer customer
Code Block
javajava

@Path("/customer")
public class CustomerService {
    
    @Context ServletContext sc;
    @Context SecurityContext sc;
    
    @PUT
    public Response updateCustomer(@Context UriInfo u, @Context HttpHeader h, Customer c) {
        ...throw new WebApplicationException(errorCode);
    }
}

Annotation inheritance


}

Similarly, annotations can be inherited from super-classes.
The resource class can also inherit the class-level annotations from either one of implemented interfaces or its subclass.

Sub-resource locators.

A method of a resource class that is annotated with @Path becomes a sub-resource locator when an annotation with an HttpMethod designator like @GET is not present. Sub-resource locators are used to further resolve the object that will handle the request. They can delegate to other sub-resource locators.

In the example below, getOrder method is a sub-resource locatorMost of the JAX-RS annotations can be inherited from either an interface or a superclass. JAX-RS specification requires that only the ones applied to methods can be inherited. For example :

Code Block
javajava
java

@Path("/customerservice/")
public class

public interface CustomerService {

    @PUT
    @Path("/customersorders/{idorderId}/")
    Response updateCustomer(Long id, Customer customerpublic Order getOrder(@PathParam("orderId") String orderId) {
        return Response.status(errorCode).build();......
    }
}
    @POST
    @Path("/customers
@XmlRootElement(name = "Order")
public class   Customer addCustomer(Customer customer) Order {
    private long id;

   throw newpublic WebApplicationExceptionOrder(errorCode); {
    }

}

@Path("/customerservice/")
public class Customers implements CustomerService    public long getId() {

    
    public Response updateCustomer(@PathParam("id"), Customer customer) {return id;
    }


    return Response.status(errorCode).build();@GET
    }
@Path("products/{productId}/")
    public CustomerProduct addCustomer(Customer customergetProduct(@PathParam("productId")int productId) {
        throw new WebApplicationException(errorCode);
    }

}

Note that annotations applied to the interface are inherited. CXF is not capable yet of inheriting the annotations applied to parameters such as PathParam so at the moment they need to be specified anyway at the root class level.

Similarly annotations can be inherited from super-classes.

CXF can inherit annotations applied directly to super-classes such as @Path("/customerservice/") which is applied to the Customers class above. It may support the same type of inheritance for interfaces too. Note this is not JAX-RS compliant.

Sub-resource locators.

A method of a resource class that is annotated with @Path becomes a sub-resource locator when an annotation with an HttpMethod designator like @GET is not present. Sub-resource locators are used to further resolve the object that will handle the request. They can delegate to other sub-resource locators.

......
    }
}

A HTTP GET request to http://localhost:9000/customerservice/orders/223/products/323 is dispatched to getOrder method first. If the Order resource whose id is 223 is found, the Order 223 will be used to further resolve Product resource. Eventually, a Product 323 that belongs to Order 223 is returned.

Note that a given subresource can be represented as an interface and resolved to an actual class at runtime. In this case any resource methods which have to be invoked on a subresource have to be inherited from a given interface In the example below, getOrder method is a sub-resource locator :

Code Block
java
java
@Path("/customerservice/")
public class CustomerService {

    @Path("/orders/{orderId}/")
    public Order getOrder(@PathParam("orderId") String orderId) {
       ......
    }
}

@XmlRootElement(name = "Order")
public classinterface Order {
    @GET
  private long id;

 @Path("products/{productId}/")
    publicProduct Order() {
    getProduct(@PathParam("productId")int productId);
}

@XmlRootElement(name    public long getId() {
        return id;= "Order")
public class OrderImpl implements Order {
    }


    @GET
    @Path("products/{productId}/")
    public Product getProduct(@PathParam("productId")int productId) {
       ......
    }
}

...

       ......
    }
}

Message Body Providers

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, File, JAXP Source, JAXB-annotated types with application/xml and application/json formats (see below). JAX-RS MultivaluedMap is also supported for
form contents. Support for other types like Reader and StreamingOutput is on the way.

...

Here's an example of a custom MessageBodyReader for InputStream (0.7 jax-rs api) :

Code Block
java
java

@ConsumeMime("application/octet-stream")
@Provider
public class InputStreamProvider implements MessageBodyReader<InputStream> {

    
    public boolean isReadable(Class<InputStream> type, Type genericType, Annotation[] annotations) {
        return InputStream.class.isAssignableFrom(type);
    }

    public InputStream readFrom(Class<InputStream> clazz, Type t, Annotation[] a, MediaType mt, 
                         Annotation[] a, MultivaluedMap<String, String> headers, InputStream is) 
        throws IOException {
        return new FilterInputStream(is) {
             @Override
             public int read(byte[] b) throws IOException {
                 // filter out some bytes
             }              
        }     
    }
}

and here's an example of a custom MessageBodyWriter for Long (0.7 jax-rs api) :

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());
        
    }

...