Apache CXF to create rest web service

I’m here to demonstrate the steps involved to create RESTful Service using Apache CXF, JAX-RS and Spring build tool that I’m going to use is Maven:

1. Start with a java web application, Maven’s mvn archetype:generate and choosing the simple webapp archetype. If you’re new to maven please refer to getting-started-with-maven.

2. Now, since I’ll be using Spring and CXF, let’s start and add the dependencies:

		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>2.2.12</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>

3. Don’t forget to alter the compiler plugin, as we’ll be using Java 6 features:

	<plugin>
	    <groupId>org.apache.maven.plugins</groupId>
	    <artifactId>maven-compiler-plugin</artifactId>
	    <configuration>
	        <source>1.6</source>
	        <target>1.6</target>
	    </configuration>
	</plugin>

4. Now that we have the api we need, we now need a service to expose. Following is the interface for the service:

public interface UserService {
	
	    public UserCollection getUsers();

	    public User getUser(Integer id);
   
	    public void newUser(Integer id, String name) throws IOException;
}

5. Since, we are using JAX-RS spec to expose REST services; here I’ll add some more annotations to the service interface:

@Path("/user-service/")
@Produces("application/xml")
public interface UserService {
	
	    @GET
	    @Path("/users")
	    public UserCollection getUsers();

	    @GET
	    @Path("/user/{id}")
	    public User getUser(@PathParam("id") Integer id);
   
	    @POST
	    @Path("/new")
		@Produces(MediaType.TEXT_HTML)
		@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
		public void newUser(
				@FormParam("id") Integer id,
				@FormParam("name") String name,
				@Context HttpServletResponse servletResponse
		) throws IOException;
	}

6. Now we only need to do some Spring configurations. First, we’ll Spring-enable the web context

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/appContext.xml</param-value>
</context-param>
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
        </listener-class>
</listener>

7. And add the CXF servlet for handling the REST calls:

<servlet>
	<servlet-name>CXFServlet</servlet-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>

8. The only thing left to do is the Spring configuration. CXF needs 3 of its own Spring configuration files, so we’ll need to import those.

<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"
	default-lazy-init="false">
	<!-- do not use import statements if CXFServlet init parameters link to 
		this beans.xml -->

	<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="userService" address="/">
		<jaxrs:serviceBeans>
			<ref bean="userServiceImpl" />
		</jaxrs:serviceBeans>
		<jaxrs:extensionMappings>
			<entry key="xml" value="application/xml" />
			<entry key="json" value="application/json" />
		</jaxrs:extensionMappings>
	</jaxrs:server>
	<bean id="userServiceImpl" class="service.impl.UserServiceImpl" />
</beans>

Finally, to run the service, use the tomcat plugin to quickly startup a Tomcat container:

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>tomcat-maven-plugin</artifactId>
	<version>1.0</version>
	<executions>
		<execution>
			<phase>pre-integration-test</phase>
			<goals>
				<goal>run-war</goal>
			</goals>
			<configuration>
				<port>8080</port>
				<path>/cxf-rest</path>
				<warFile>
					${project.basedir}/target/${project.build.finalName}.war
    			</warFile>
				<fork>true</fork>
			</configuration>
		</execution>
	</executions>
</plugin>

Now use, mvn tomcat:run-war to start the tomcat and have a look at your web service.

ANNEXTURE: JAX-RS Annotation quick reference-

Bean Annotation and parameters
@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 and may include arbitrary regular expressions. When not available on the resource method, it’s inherited from a class.
HTTP Method: 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 for e.g.

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

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

@Path("/user/{id}")
	public User getUser(@PathParam("id") Integer id);

@QueryParam annotation is used to extract URI query parameter from the HTTP request. @QueryParam allows you to inject URL query parameters into any primitive type as well as any class that either has a public static valueOf(String) method or a constructor that takes one parameter of type String.

@Path("/users")
public UserCollection getUers(@QueryParam("size") 
@DefaultValue("50") int size){
   	}

@HttpHeader, @MatrixParam, @FormParam and @CookieParam annotations are also supported.

Media types: Consider this resource class with 2 resource methods:

@Path("/")
public class Test1 {

 @Path("/adduser")
 @POST 
 @Consumes({"application/json", "application/xml"})
 @Produces({"application/json", "application/xml"})
 public User addUser(UserDetails details) {...}
}

For this specific example, in both cases either JAXB or JSON message body readers and writers will be selected to deserialize the input stream into UserDetails and serialize User into the output stream. Message body providers can have @Produces and @Consumes set too, and they have to match those on a chosen resource method.

Source Code: cxf-rest, Sushant

Resources:
1. http://cxf.apache.org/docs/jax-rs.html
2. ReSTful concepts
3. Getting Started with maven

Advertisements