You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 15 Next »

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.

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

Understanding the basics

You are encouraged to read JAX-RS spec to find out information not covered by this documentation.

Resource class

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

package demo.jaxrs.server;

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

import javax.ws.rs.HttpMethod;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.UriParam;
import javax.ws.rs.UriTemplate;
import javax.ws.rs.core.HttpContext;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

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

    public CustomerService() {
    }

    @HttpMethod("GET")
    @UriTemplate("/customers/{id}/")
    public Customer getCustomer(@UriParam("id") String id) {
        ......
    }

    @HttpMethod("PUT")
    @UriTemplate("/customers/")
    public Response updateCustomer(Customer customer) {
        ......
    }

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

    @HttpMethod("DELETE")
    @UriTemplate("/customers/{id}/")
    public Response deleteCustomer(@UriParam("id") String id) {
        ......
    }

    @UriTemplate("/orders/{orderId}/")
    public Order getOrder(@UriParam("orderId") String orderId) {
       ......
    }
}

@UriTemplate

@UriTemplate annotation is applied to resource classes or methods. The value of @UriTemplate annotation is a relative URI path follows the URI Template format. More information about URI Templates can be found from JAX-RS spec section 2.3.

@HttpMethod

@HttpMethod specifies the HTTP verb (GET, PUT, POST,DELETE) a method can accept.

Sub-resource locators.

A method of a resource class that is annotated with @UriTemplate becomes a sub-resource locator when @HttpMethod is not present. Sub-resource locators are used to further resolve the object that will handle the request. In the example below, getOrder method is a sub-resource locator:

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

    @UriTemplate("/orders/{orderId}/")
    public Order getOrder(@UriParam("orderId") String orderId) {
       ......
    }
}

@XmlRootElement(name = "Order")
public class Order {
    private long id;
    private String description;

    public Order() {
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String d) {
        this.description = d;
    }

    @HttpMethod("GET")
    @UriTemplate("products/{productId}/")
    public Product getProduct(@UriParam("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.

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 support

The request and response can be marshaled and unmarshaled to/from Java object using JAXB. The Java object needs to be marked with @XmlRootElement annotation. For example:

@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:

@UriTemplate("/customerservice/")
public class CustomerService {
    @HttpMethod("GET")
    @UriTemplate("/customers/{customerId}/")
    public Customer getCustomer(@UriParam("customerId") String id) {
        ....
    }
}

The wire representation of Customer object is:

@UriTemplate("/customerservice/")
<Customer>
    <id>123</id>
    <name>John</name>
</Customer>

To work with collections, you need to define an object collection type. For example:

@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;
    }
}
@UriTemplate("/customerservice/")
public class CustomerService {
    @HttpMethod("GET")
    @UriTemplate("/customers/")
    public Customers getCustomers() {
        ....
    }
}

JSON support

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

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

The wire representation of Customer object is:

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

DOMSource support

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

@UriTemplate("/customerservice/")
public class CustomerService {
    @HttpMethod("PUT")
    @UriTemplate("/customers/")
    public javax.xml.transform.dom.DOMSource updateCustomer(javax.xml.transform.dom.DOMSource ds) {
        ....
    }
}

Secure JAX-RS services

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

Configuring JAX-RS services

Configuring JAX-RS services programmatically

You can create a JAX-RS RESTful service by using JAXRSServerFactoryBean from the cxf-rt-frontend-jaxrs package:

JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setAddress("http://localhost:9000/");
sf.create();

A couple things to note:

  • The JAXRSServerFactoryBean creates a Server inside CXF which starts listening for requests on the URL specified.
  • By default, the JAX-RS runtime is responsible for the lifecycle of resource classes, default lifecycle is per-request. You can set the lifecycle to singleton by using following line:
    sf.setResourceProvider(BookStore.class, new SingletonResourceProvider());
    
  • If you prefer not to let the JAX-RS runtime to handle the resource class lifecycle for you (for example, it might be the case that your resource class is created by other containers such as Spring), you can do following:
    JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
    CustomerService cs = new CustomerService();
    sf.setServiceBeans(cs);
    sf.setAddress("http://localhost:9080/");
    sf.create();
    

Configuring JAX-RS services in container with Spring configuration file.

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/beans.xml</param-value>
	</context-param>

	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<display-name>CXF Servlet</display-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxrs="http://cxf.apache.org/jaxrs"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

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

</beans>
  • No labels