Versions Compared

Key

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

...

Code Block
java
java
package demo.jaxrs.server;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;

@Path("/customerservice/")
@Produces("application/xml")
public class CustomerService {

    public CustomerService() {
    }

    @GET
    public Customers getCustomers() {
        ......
    }

    @GET
    @Path("/customers/{id}")
    @Produces("application/json")
    public Customer getCustomer(@PathParam("id") String id) {
        ......
    }

    @PUT
    @Path("/customers/{id}")
    @Consumes("application/xml")
    public Response updateCustomer(@PathParam("id") Long id, Customer customer) {
        ......
    }

    @POST
    @Path("/customers")
    public Response addCustomer(Customer customer) {
        ......
    }

    @DELETE
    @Path("/customers/{id}/")
    public Response deleteCustomer(@PathParam("id") String id) {
        ......
    }

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

...

JAX-RS specification defines a number of annotations such as @GET, @PUT, @POST and @DELETE. Using an @HttpMethod designator, one can create a custom annotation such as @Update or @Patch

Return types

. For example :

Code Block
java
java

package org.apache.cxf.customverb;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH { 
}

Return types

Either javax.ws.rs.core.Response or custom type can be returned. javax.ws.rs.core.Response can be used to set the HTTP response code, headers and entity. JAX-RS MessageBodyWriters (Either javax.ws.rs.core.Response or custom type can be returned. javax.ws.rs.core.Response can be used to set the HTTP response code, headers and entity. JAX-RS MessageBodyReaders (see below) are in charge of serializing the response entities, those which are returned directly or as part of javax.ws.rs.core.Response.

...

Code Block
java
java

    public Response updateCustomer(@DefaultValue("123") @QueryParam("id") Long id, @PathParam("name") String name) { ... }

JAX-RS mandates that only a single method parameter which is not annotated with JAXRS annotations applicable to method parameters is allowed in a resource method. For example :

Code Block
java
java

public Response do(@PathParam("id") String id, String body) {
}

Parameters like 'String body' are expected to represent the request body/input stream. It's the job of JAX-RS MessageBodyReaders to deserialize the request body into an object of the expected type.

There's also a CXF extension which makes it possible to There's also a CXF extension which makes it possible to inject a sequence of @PathParam, @QueryParam, @FormParam or @MatrixParam parameters into a bean. For ex :

...

A number of context types can be injected as parameters, in fields or through dedicated methods.
UriInfo, SecurityContext, HttpHeaders, MessageBodyWorkersProviders, Request, ContextResolver, Servlet types such as HttpServletRequest
can be injected(HttpServletRequest, HttpServletResponse, ServletContext, ServletConfig) can be injected.

A CXF-specific composite context interface, MessageContext is also supported which makes it easier to deal with all the supported JAX-RS contexts (and indeed with the future ones) and also lets check the current message's properties.

Example :

Code Block
java
java
@Path("/customer")
public class CustomerService {
    
    @Context 
    private org.apache.cxf.jaxrs.ext.MessageContext mc; 
    @Context 
    private ServletContext sc;
    private UriInfo ui;
    
    @Context
    public void setUriInfo(UriInfo ui) {
        this.ui = ui;
    }

    @PUT
    public Response updateCustomer(@Context HttpHeaders h, Customer c) {
        ...mc.getHttpHeaders();
    }
}

Note that all types of supported JAX-RS providers such as MessageBodyWriter, MessageBodyReader, ExceptionMapper and ContextResolver, as well as the list of body providers which can be provided by MessageBodyWorkers Providers can have contexts injected too. The only exception is that no parameter level injection is supported for providers due to provider's methods being fixed.

Note that MessageBodyWorkers Providers and ContextResolver are likely to be of interest to message body providers rather than to the actual application code. You can also inject Servlet all the context types into @Resource annotated fields. Other types would likely be supported too.

Annotation inheritanceAnnotation 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 :

...

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

...

A method of a resource class that is annotated with @Path becomes a sub-resource locator when an no 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, including themselves.

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 class Order {
    private long id;
    private Items items;

    public Order() {
    }

    public long getId() {
        return id;
    }


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

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 :

Code Block
javajava

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

    @Path("/orders/{orderId}/")
    public Order getOrder(@PathParam("orderId") String orderId
    @Path("products/{productId}/items")
    public Order getItems(@PathParam("productId") int productId) {
       return this;
    }

    @GET
    public Items getItems() {
       ......
    }
}

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

@XmlRootElement(name = "Order")
public class OrderImpl implements Order {
    
    public Product getProduct(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, 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.

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:


}

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.
The request to http://localhost:9000/customerservice/orders/223/products/323/items will be delivered to getItems() method which in turn will delegate to an overloaded getItems().

Note that a subresource class like Order is often has no root @Path annotations which means that they're delegated to dynamically at runtime, in other words, they can not be invoked upon before one of the root resource classes is invoked first. A root resource class (which has a root @\Path annotation) can become a subresource too if one of its subresource locator methods delegates to it, similarly to Order.getItems() above.

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 :

code
Code Block
java
java
@Path("/customerservice/")
public class CustomerService {
    @ProduceMime("application/json")
    @GET
    @Path("/customersorders/{customerIdorderId}/")
    public CustomerOrder getCustomergetOrder(@PathParam("customerIdorderId") String idorderId) {
        ......
    }

The wire representation of Customer object is:

...


{"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
javajava

@Path("/customerservice/")
public class CustomerService }

public interface Order {
    @PUT@GET
    @Path("products/customers{productId}/")
    public javax.xml.transform.Source updateCustomer(javax.xml.transform.Source ds)Product getProduct(@PathParam("productId")int productId);
}

@XmlRootElement(name = "Order")
public class OrderImpl implements Order {
    
    public Product getProduct(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, Reader, File, JAXP Source, JAX-RS StreamingOutput, JAXB-annotated types with application/xml, text/xml and application/json formats as well as JAXBElement (see below). JAX-RS MultivaluedMap is also supported for form contents.

See also a "Support for data bindings" section below.

Custom Message Body Providers

It's likely that a given application may need to deal with types which are not supported by default.
It's likely that a given application may need to deal with types which are not supported by default.
Alternatively, developers may want to provide a more efficient support for handling default types such as InputStream.

...

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.

Configuring JAXB provider

The default JAXB provider can be configured in a number of ways. For example, here's how to set up marshall properties :

Code Block
xml
xml

<beans xmlns:util="http://www.springframework.org/schema/util">
<bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
<property name="marshallerProperties" ref="propertiesMap"/>
</bean>
<util:map id="propertiesMap" map-class="java.util.Hashtable">
<entry key="jaxb.formatted.output" value="true"/>
</util:map>
/<beans>

Individual marshal properties can be injected as simple properties. At the moment, Marshaller.JAXB_SCHEMA_LOCATION can be injected as "schemaLocation" property. Schema validation can be enabled and custom @Consume and @Produce media types can be injected, see this example and other sections below for more information.

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"}}

Aegis Data Binding

Use org.apache.cxf.provider.AegisElementProvider to start doing Aegis with JAX-RS

...