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

About sushant
Tech enthusiast working on java/j2ee, loves to explore as well as stay focused with core programming.

28 Responses to Apache CXF to create rest web service

    • You are right, @Produces({“application/json”, “application/xml”}) annotation will allow you to provide both representations to your resource. While making the request to webservice, set Accept headers to desired representation.

  1. kavitha says:

    @Produces({“application/json”, “application/xml”})

  2. Ramesh says:

    Hi Sushant,
    Honestly, this is one of the best tutorial for CXF, Spring or getting started with Apache CXF. Very simple and concise.

    Thanks
    Ramesh

  3. Atish says:

    Hi Sushant,
    I am using the same framework for my project.
    Now I have a requirement where I have to alter the incoming JSON body before my service consumes it.

    I see lot of interceptors are present to do that. but failed to get any progress.

    Can you help

    • Sure Atish,
      If you have understood how to intercept the request, you’re not very far from reaching the solution. Let me know in detail the challenges you’re facing. If you can’t port the details here, I’ll drop you a mail and you can reply back.

  4. Amit says:

    Hi Sushant,

    Your tutorial is very useful. In order to get it running could you please share the complete source code.

    • Though I discourage the practice of providing all code as even if learner will copy paste the code from post, he will still do some hands on but as you asked for it, I’ll mail you the project code.

  5. Joe says:

    Excelent article

    Please send me the code to my e-mail

  6. Hi Sushant,

    I am new to Restful Web Services, this is helps a lot.

    Thanks a ton for the simple but great article..

    Will you please mail the project code to my e-mail.

    Thanks in advance.

  7. Nripa says:

    Great ! Can some body help me sending this code to my email.
    Thank you in advace

    regards
    Nripa

  8. Hi Nripa,

    I’ve sent you a mail containing the code.

    Readers please avoid posting your mail in comment section to avoid misuse, anyway wordpress collects it as mail-id box and I get to know that.

    WordPress don’t allow to upload the code, any clean service where I can?

    ..
    Sushant

  9. Vivek says:

    Could you upload the code to github?

  10. Uma Mahesh Addula says:

    hey dude
    this helped me a lot
    Uma mahesh, your old colleague.

  11. Could you please share the code?

  12. This was a really great piece of information. As the owner of Dot Solutions And Technology I can appreciate everything that you have said here. Keep up the great work.

  13. Vaibhav Shukla says:

    unable to access the source code. Please email me. Thank you!

  14. Vaibhav Shukla says:

    Hi sushant
    I tried running your code but getting compiler errors on annotations in service class. I geuss few jars are missing. I tried clean-install the pom but again got some test errors saying “could not send message”
    Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.10:test (default-test) on project cxf-rest: There are test failures.
    etc etc. Please tell what m i missing? Or if you have a readme for the project, it would be highly helpful.
    Thanks alot

    • sushant says:

      I guess you haven’t setup maven correctly. Do you have internet connection? direct or thru proxy? As long as connectivity is there, maven will take care of downloading of respective jars.
      For test failures, you will need to look at the respective Sunfire reports/logs to understand the exact reason and area of errors.

  15. Paolo says:

    Hi, I don’t see service.impl.UserServiceImpl… I imagine it needs to be created too

  16. Harikrishna says:

    Hi Sushanth

    Can u please email me the source Code Thanks One again for such a useful post

  17. Pingback: Как поднять CXF Servlet « dev-blogs.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: