Learn in Java
 


   

Restful WebService using Jersey

 
Any service which follows the REST(REpresentational State Transfer) architectural pattern is said to be restful. Let us look at an example on how to create a simple restful webservice using Jersey and Spring. The following software has been used for this tutorial :
    1. Apache Maven 3.0.4
    2. Spring 3.2.6
    3. Jersey 1.19
    4. Jetty 6.1.10 or Tomcat 7
    

First, we need to create a basic Jersey web project structure.

Create a basic maven web project structure similar to below :

jerseyjaxrsws
|   pom.xml
|
+---.settings
+---src
|   +---main
|   |   +---java
|   |   |   +---com
|   |   |       +---learninjava
|   |   |               HelloAngryWorld.java
|   |   |               JsonBean.java
|   |   |
|   |   +---webapp
|   |       +---META-INF
|   |       |       MANIFEST.MF
|   |       |
|   |       +---WEB-INF
|   |               beans.xml
|   |               web.xml
|   |
|   +---test
|       +---java
|           +---com
|               +---learninjava
|                       HelloAngryWorldTest.java

Remember:
You MUST use the Test case file name pattern as below because the maven surefire plugin expects the test file 
names in the following patterns :

    **/Test*.java
    **/*Test.java
    **/*TestCase.java
    

For your convenience, we have provided configurations for running the webservice on both Jetty and Tomcat servers.

First, let us take a look at tomcat configuration. Later we will see about jetty configuration. There is a cool feature in jetty that attracts many developers. we will see what is it later in this tutorial.

Using Tomcat :

1. pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
	<modelVersion>4.0.0</modelVersion>
    <groupId>com.learninjava</groupId>
    <artifactId>jerseyjaxrsws</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>jerseyjaxrsws Jersey Webapp</name>
	
	<organization>
        <name>Learn in Java</name>
        <url>http://www.learninjava.com/</url>
    </organization>
	<!-- Change the version numbers or other configurations here -->
    <properties>
        <jersey.version>1.19</jersey.version>
        <spring.version>3.2.6.RELEASE</spring.version>
        <junit.version>4.11</junit.version>
        <surefire.version>2.10</surefire.version>
        <tomcat7.version>2.0</tomcat7.version>
        <compiler.srcversion>1.7</compiler.srcversion>
        <compiler.tgtversion>1.7</compiler.tgtversion>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <port.number>9090</port.number>
		<service.url>http://localhost:${port.number}/jaxrs-service</service.url>
    </properties>
	
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
		
        <!-- Dependencies for Jersey Client Starts -->
		<!--<dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey.version}</version>
        </dependency>-->
		<!-- Dependencies for Jersey Client Ends -->
		
		<!-- Dependencies for Pure JAX-RS Client Starts -->
		<dependency>
			<groupId>org.glassfish.jersey.containers</groupId>
			<artifactId>jersey-container-servlet</artifactId>
			<version>2.17</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.core</groupId>
			<artifactId>jersey-client</artifactId>
			<version>2.17</version>
			<scope>provided</scope>
		</dependency>
		<!-- Dependencies for Pure JAX-RS Client Ends -->
		
		<!-- Jersey & Spring Dependencies(excluding dependencies that are not required) -->
		<dependency>
			<groupId>com.sun.jersey.contribs</groupId>
			<artifactId>jersey-spring</artifactId>
			<version>${jersey.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-web</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-aop</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-asm</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-beans</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-context</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

	</dependencies>
    <build>
        <pluginManagement>
        <plugins>
            
			<!-- Optional plugin, This is added to specify service.url in pom.xml itself -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>${surefire.version}</version>
				<configuration>
					<argLine>-Dservice.url=${service.url}</argLine>
				</configuration>
			</plugin>

			<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <inherited>true</inherited>
                <configuration>
                    <source>${compiler.srcversion}</source>
                    <target>${compiler.tgtversion}</target>
                </configuration>
            </plugin>

			<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>${tomcat7.version}</version>
				<executions>
					<execution>
						<id>default-cli</id>
						<goals>
							<goal>run</goal>
						</goals>
						<configuration>
							<port>${port.number}</port>
							<path>/jaxrs-service</path>
							<useSeparateTomcatClassLoader>true</useSeparateTomcatClassLoader>
						</configuration>
					</execution>
				</executions>
			</plugin>
				
			<!-- Optional plugin, This is added to create an eclipse compatible project. To do it, use : mvn eclipse:eclipse -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<configuration>
					<projectNameTemplate>[artifactId]-[version]</projectNameTemplate>
					<wtpmanifest>true</wtpmanifest>
					<wtpapplicationxml>true</wtpapplicationxml>
					<wtpversion>2.0</wtpversion>
				</configuration>
			</plugin>
        </plugins>
		</pluginManagement>
    </build>

</project>

You will notice that there are 4 important plugins in the pom.xml out of which 2 are optional. We will see each of them in detail :

maven-surefire-plugin -  [Optional] This plugin is added to specify the service.url in the pom.xml itself. We will see its 
usage while running the web service client.
maven-compiler-plugin - This plugin specifies the Java compiler source and target versions.
tomcat7-maven-plugin - This is the tomcat plugin where will be deploy our angry world webservice.
maven-eclipse-plugin - [Optional] This plugin is used to generate the .classpath and .project files which enables us to use 
this project in eclipse.

The other important sections includes dependencies and properties which are used to specify the jar file dependencies and properties respectively. We have commented out a certain section of dependencies. We will see that when we create a client,Restful client using Jersey


 

2. HelloAngryWorld.java :

package com.learninjava;

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

/**
 * @author learninjava.com
 * @see www.learninjava.com
 */
@Path("/helloAngryWorld")
public class HelloAngryWorld {

    @GET
    @Path("/echo/{input}")
    @Produces("text/plain")
    public String ping(@PathParam("input") String input) {
        return input;
    }

    @POST
    @Produces("application/json")
    @Consumes("application/json")
    @Path("/jsonBean")
    public Response modifyJson(JsonBean input) {
        input.setVal2(input.getVal1());
        return Response.ok().entity(input).build();
    }
}

This is the actual webservice source file, so lets take a look at it.

This webservice exposes two methods one of type plain text and other of type JsonBean. These methods uses some important annotations:

@Path annotation at class level specifies the context path to access this webservice.
@Path annotation at method level specifies the path to access the actual method in the webservice.
@PathParam annotation is used to accept input from the request URL path specified by @Path.
@Produces annotation is used to specify the return type of the method.
@Consumes annotation is used to specify the return type accepted as input to a method.

For a complete listing of annotations refer : http://java-hub.blogspot.in/2015/01/jax-rs-annotations.html

3. JsonBean.java :

package com.learninjava;

/**
 * @author learninjava.com
 * @see www.learninjava.com
 */
public class JsonBean {
    private String val1;
    private String val2;

    public String getVal1() {
        return val1;
    }

    public void setVal1(String val1) {
        this.val1 = val1;
    }

    public String getVal2() {
        return val2;
    }

    public void setVal2(String val2) {
        this.val2 = val2;
    }

}

4. 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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    <context:property-placeholder/>
    <context:annotation-config/>
    <bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"/>
    <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"/>

    <bean class="com.learninjava.HelloAngryWorld" name="helloAngryWorld"/>

</beans>

PreferencesPlaceholderConfigurer and ServletContextPropertyPlaceholderConfigurer are used to handle properties files. See references section at the bottom of this tutorial for more information.

The most significant part of beans.xml is the bean definition of the webservice we are going to expose.

5. web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
    <display-name>Simple Jersey Restful Service</display-name>
    <description>Simple Jersey Restful Service</description>
    
    <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>jersey-serlvet</servlet-name>
<!--        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>-->
			<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.learninjava</param-value>
        </init-param>
        <init-param>
          <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
          <param-value>true</param-value>
        </init-param>		
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
	
</web-app>

The configurations in web.xml are straighforward. SpringServlet is the actual servlet that reads the xml configurations and makes the service beans as webservices and handles the requests and responses to the exposed services.

Remember:
Observe that SpringServlet is spring enabled servlet for exposing webservices using Jersey. If we dont want to use Jersey
then you can use ServletContainer instead(disabled in web.xml).

ContextLoaderListener is the ROOT web application context that is used by spring.

com.sun.jersey.config.property.packages - specifies the package name for the webservice artifacts

POJOMappingFeature is responsible for mapping java objects to JSON.

Once the above files are ready, type the below command to start the tomcat container :

mvn clean package -DskipTests=true tomcat7:run

This command cleans the target directory, compiles, builds war and deploys it to tomcat. Notice that we used skipTests = true switch. This is to make sure that the test case are not run before the server starts.

Navigate to the URL :

http://localhost:9090/jaxrs-service/helloAngryWorld/echo/tweet

Output:
tweet

This is an echo service so whatever you input in the URL should be echoed to your browser.

Using Jetty :

1. pom.xml :

The pom.xml is pretty much similar to the one we have used for tomcat configuration except that the tomcat plugin is replaced with the jetty equivalent. Also the port number is changed 8080 just to distinguish between tomcat and jetty.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
	<modelVersion>4.0.0</modelVersion>
    <groupId>com.learninjava</groupId>
    <artifactId>jerseyjaxrsws</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>jerseyjaxrsws Jersey Webapp</name>
	
	<organization>
        <name>Learn in Java</name>
        <url>http://www.learninjava.com/</url>
    </organization>
	<!-- Change the version numbers or other configurations here -->
    <properties>
        <jersey.version>1.19</jersey.version>
        <spring.version>3.2.6.RELEASE</spring.version>
        <junit.version>4.11</junit.version>
        <surefire.version>2.10</surefire.version>
        <jetty.version>6.1.10</jetty.version>
        <compiler.srcversion>1.7</compiler.srcversion>
        <compiler.tgtversion>1.7</compiler.tgtversion>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <port.number>8080</port.number>
		<service.url>http://localhost:${port.number}/jaxrs-service</service.url>
    </properties>
	
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
		
        <!-- Dependencies for Jersey Client Starts -->
		<!--<dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey.version}</version>
        </dependency>-->
		<!-- Dependencies for Jersey Client Ends -->
		
		<!-- Dependencies for Pure JAX-RS Client Starts -->
		<dependency>
			<groupId>org.glassfish.jersey.containers</groupId>
			<artifactId>jersey-container-servlet</artifactId>
			<version>2.17</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.core</groupId>
			<artifactId>jersey-client</artifactId>
			<version>2.17</version>
			<scope>provided</scope>
		</dependency>
		<!-- Dependencies for Pure JAX-RS Client Ends -->
		
		<!-- Jersey & Spring Dependencies(excluding dependencies that are not required) -->
		<dependency>
			<groupId>com.sun.jersey.contribs</groupId>
			<artifactId>jersey-spring</artifactId>
			<version>${jersey.version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-web</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-aop</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-asm</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-beans</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-context</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

	</dependencies>
    <build>
        <pluginManagement>
        <plugins>
		
			<!-- Optional plugin, This is added to specify service.url in pom.xml itself -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>${surefire.version}</version>
				<configuration>
					<argLine>-Dservice.url=${service.url}</argLine>
				</configuration>
			</plugin>
		
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <inherited>true</inherited>
                <configuration>
                    <source>${compiler.srcversion}</source>
                    <target>${compiler.tgtversion}</target>
                </configuration>
            </plugin>

			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>${jetty.version}</version>
				<configuration>
					<scanIntervalSeconds>10</scanIntervalSeconds>
					<connectors>
						<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
							<port>${port.number}</port>
							<maxIdleTime>60000</maxIdleTime>
						</connector>
					</connectors>
					<webAppConfig>
						<contextPath>/jaxrs-service</contextPath>
					</webAppConfig>
			  </configuration>
			</plugin>
				
			<!-- Optional plugin, This is added to create an eclipse compatible project. To do it, use : mvn eclipse:eclipse -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<configuration>
					<projectNameTemplate>[artifactId]-[version]</projectNameTemplate>
					<wtpmanifest>true</wtpmanifest>
					<wtpapplicationxml>true</wtpapplicationxml>
					<wtpversion>2.0</wtpversion>
				</configuration>
			</plugin>
        </plugins>
		</pluginManagement>
    </build>
</project>

All other steps are same as above.

To start the jetty container and the webservice use the below command :

mvn clean package -DskipTests=true jetty:run

Navigate to the URL :

http://localhost:8080/jaxrs-service/helloAngryWorld/echo/tweet

Output:
tweet

Advantage of using Jetty - Hot code deployment :

By default, Jetty scans the following directories :

  target/classes  -  for changes to Java sources and 
  src/main/webapp -  for changes to web sources. 

If any source file is modified, the changes are autodeployed to the jetty container without manually restarting for the changes to take effect.

To test this hot code deployment, try to change any source file. We have changed the Path param of ping method from echo to ping. Now, recompiled the source using mvn compile command.

The moment the source file is compiled, notice the server console. You will observe that jetty hot deploys the code automatically and you can access the changes via browser instantly.

Navigate to the URL :

http://localhost:8080/jaxrs-service/helloAngryWorld/ping/tweet

Output:
tweet


References :

PreferencesPlaceholderConfigurer

ServletContextPropertyPlaceholderConfigurer

 
   

Related Articles

Restful WebService using CXF
Restful Client using CXF
SOAP WebService using CXF
SOAP Client using CXF
Restful Client using Jersey
 
   

Recommended Articles

User and Daemon Threads
Thread States
Java 8 Stream
Java 8 Functional Interfaces
Java 8 Lambda Expressions
Top 10 Free Tutorials




LIKE/SHARE
 
 
 
Download Source:

Comments:


 

Top Picks

1. Top 5 websites offering free e-books

2. Top 10 websites for free Java Articles and Tutorials

3. Top 5 websites for Java Certifications

4. Top 5 Softwares for Java developers




   
   
   
 
 
© Copyright 2017. All rights reserved. All trademarks and logos belongs to their owners.         Website Counter