Thursday, December 23, 2010

Writing JAX-RS REST API Server with Jersey / GlassFish v3

Writing REST API Web Service application in Java EE 6 is now trivial with JAX-RS API and Jersey (the reference implementation of JAX-RS, bundled with GlassFish v3). I'll show you how, with raw real code. ;-)

Requirements

  1. Eclipse IDE, pick the Java EE edition. Latest version is 3.6 SR1 (Helios)
  2. JBoss Tools plugin for Eclipse IDE (probably optional)
  3. A Java EE 6 Server like GlassFish v3 or JBoss AS 6 (not GA yet)

Create the Web (WAR) Project


Create a new Dynamic Web project in Eclipse.

You'll need to choose a Java EE container runtime, it will download the libraries ("Java EE 6 SDK") as well.

Implement the Resource Class


Create a new JAX-RS resource class. What makes it a resource class is you sprinkle it with javax.ws.rs.Path annotation.

I use JBoss Tools and GlassFish server plugin for Eclipse so either or both of them adds the Java EE libraries to my build path, including the most important  here is jsr311-api.jar. If you use Maven you can depend on javax.ws.rs:jsr311-api:1.1.1 artifact.
A sample resource class is like below. Note that I split my resource class to interface and implementation class.

package com.abispulsa.bisnis.service;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;

import org.eclipse.emf.ecore.EObject;

/**
* <!-- begin-user-doc -->
* A representation of the model object '<em><b>Refiller</b></em>'.
* <!-- end-user-doc -->
*
* <!-- begin-model-doc -->
* Refill the target mobile number by some amount.
*
* This is the public facing REST API.
* <!-- end-model-doc -->
*
* <p>
* The following features are supported:
* <ul>
*   <li>{@link com.abispulsa.bisnis.service.Refiller#getSession <em>Session</em>}</li>
* </ul>
* </p>
*
* @see com.abispulsa.bisnis.service.ServicePackage#getRefiller()
* @model
* @generated
*/
public interface Refiller extends EObject {

/**
* <!-- begin-user-doc -->
* This actually only queues it. The real work is done in the queue processor job.
* <!-- end-user-doc -->
* @model
* @generated
*/
@Path("refill")
@POST
String refill(@FormParam("mobileNumber") String mobileNumber, @FormParam("voucherCode") String voucherCode);

} // Refiller

You may notice I'm using the mighty EMF to design the resource class. Yes, that's right! ;-)
(ok, so that's the excuse for me for posting this article to EclipseDriven, I'm hoping people will be curious "what's EMF? sounds cool!" hahahaha)

Ok so here's the actual resource class :

package com.abispulsa.bisnis.service.impl;

import javax.ws.rs.Path;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;

import com.abispulsa.bisnis.service.Refiller;
import com.abispulsa.bisnis.service.ServicePackage;
import com.abispulsa.bisnis.service.Session;

/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Refiller</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
*   <li>{@link com.abispulsa.bisnis.service.impl.RefillerImpl#getSession <em>Session</em>}</li>
* </ul>
* </p>
*
* @generated
*/
@Path("/")
public class RefillerImpl extends EObjectImpl implements Refiller {

/**
* <!-- begin-user-doc -->
* Make it public constructor for used in JAX-RS.
* We should wrap it inside application and use CDI though.
* <!-- end-user-doc -->
* @generated NOT
*/
public RefillerImpl() {
super();
}


/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public String refill(String mobileNumber, String voucherCode) {
return String.format("MobileNumber=%s voucherCode=%s", mobileNumber, voucherCode);
...
}

private void checkAuthentication() {
// TODO Auto-generated method stub

}

...

} //RefillerImpl

There are several things to notice here:

  1. The implementation resource class is @Path annotated. Of course, since you can't instantiate an interface!
  2. It's possible to "split" JAX-RS annotations between interface, class, interface methods and class method. In my example, the interface defines the the REST API and specific structure of the service. However, the implementation can decide where to put the service itself using @Path. The implementation do not override any of the JAX-RS annotations (REST API structure) defined by the interface.
  3. A public constructor is needed (EMF generated default constructor is protected, there is a reason why), because Jersey will instantiate the resource class directly. It's possible to implement javax.ws.rs.Application so you can instantiate your resource classes yourself and configure Jersey for that. More on this later.

Configuring web.xml for Jersey


The last thing is you need to configure the Jersey servlet in your web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">

<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.abispulsa.bisnis.service.impl</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/api/v1/*</url-pattern>
</servlet-mapping>

<session-config>
<session-timeout>30</session-timeout>
</session-config>

</web-app>

The web.xml above tells the Java EE 6 Container (i.e. GlassFish v3) to:

  1. Create a Jersey servlet at URL path: /api/v1
  2. Load JAX-RS resource classes from my package:
com.abispulsa.bisnis.service.impl com.sun.jersey.config.property.packages init-param contains a comma-separated list of package names (so you can list multiple packages there). Note that this is optional. I use it because my Web/WAR project doesn't actually contain these packages, but the packages are provided by another JAR that I included in WEB-INF/lib. If your resource classes are inside the WAR itself (i.e. built to WEB-INF/classes) you can leave out that configuration and Jersey will find your classes just fine.

Deploy the Web Project


Deploying the app into GlassFish v3 outputs the following log:

INFO: Scanning for root resource and provider classes in the packages:
  com.abispulsa.bisnis.service.impl
INFO: Root resource classes found:
  class com.abispulsa.bisnis.service.impl.RefillerImpl
INFO: No provider classes found.

INFO: GlobalStatsProvider registered
INFO: Initiating Jersey application, version 'Jersey: 1.1.5 01/20/2010 04:04 PM'
INFO: Adding the following classes declared in META-INF/services/jersey-server-components to the resource configuration:
  class com.sun.jersey.multipart.impl.FormDataMultiPartDispatchProvider
  class com.sun.jersey.multipart.impl.MultiPartConfigProvider
  class com.sun.jersey.multipart.impl.MultiPartReader
  class com.sun.jersey.multipart.impl.MultiPartWriter

INFO: Loading application com.abispulsa.bisnis.server.rest at /apbrest
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.

INFO: com.abispulsa.bisnis.server.rest was successfully deployed in 8.179 milliseconds.

Testing the JAX-RS REST API Server with curl

Ok so now l want to test it, using curl is my favorite (in Ubuntu/Debian you can just sudo apt-get install curl), but you can use any tool that understands HTTP requests.

ceefour@annafi:~/project/AbisPulsa/workspace/com.abispulsa.bisnis.service$ curl -v --data-urlencode mobileNumber=08123456 --data-urlencode voucherCode=A5 'http://localhost:8080/apbrest/api/v1/refill'

* About to connect() to localhost port 8080 (#0)
*   Trying ::1... connected
* Connected to localhost (::1) port 8080 (#0)
> POST /apbrest/api/v1/refill HTTP/1.1
> User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: localhost:8080
> Accept: */*
> Content-Length: 36
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 200 OK
< X-Powered-By: Servlet/3.0
< Server: GlassFish Server Open Source Edition 3.0.1
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Thu, 23 Dec 2010 09:34:31 GMT
<
* Connection #0 to host localhost left intact
* Closing connection #0
MobileNumber=08123456 voucherCode=A5

Alright! So I guess my application works! ;-)

Pretty straightforward, huh?

Using your Own javax.ws.rs.core.Application Implementation


As mentioned before, Jersey will create your resource classes.

If you want to control instantiation of your classes, you can create class that implements javax.ws.rs.core.Application.

After that you configure it in your web.xml like this:

<web-app> <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>MyApplication</param-value> </init-param> </servlet>     ....
I haven't tried it yet, but I think one probable use case is if you want to use Dependency Injection (CDI) in your resource classes.......... ALTHOUGH GlassFish already does this for you (you can use JAX-RS and CDI at the same time), so you probably only use Application for this purpose if the container doesn't support integration between these specs.

Say Goodbye to web.xml


Another, more valid use case and I guess more common if you want to be "pure Java EE 6" is to leave out web.xml altogether:
JAX-RS 1.1 offers a @ApplicationPath annotation applicable to javax.ws.rs.core.Application which let you specify the webcontext and remove the need for any web.xml

References

6 comments:

polo outlet said...

http://www.superbagsmarket.com/
http://www.superbagsmarket.com/louis-vuitton-bags-c-1.html
http://www.superbagsmarket.com/hermes-bags-c-2.html
http://www.superbagsmarket.com/prada-bags-c-3.html
http://www.superbagsmarket.com/chanel-bags-c-4.html
http://www.superbagsmarket.com/gucci-bags-c-5.html
http://www.superbagsmarket.com/burberry-bags-c-6.html
http://www.superbagsmarket.com/celine-bags-c-7.html
http://www.superbagsmarket.com/balenciaga-bags-c-8.html
http://www.superbagsmarket.com/christian-dior-bags-c-9.html
http://www.superbagsmarket.com/chloe-bags-c-10.html
http://www.superbagsmarket.com/bvlgari-bags-c-11.html
http://www.superbagsmarket.com/bally-bags-c-12.html
http://www.superbagsmarket.com/coach-bags-c-13.html
http://www.superbagsmarket.com/michael-kors-bags-c-14.html
http://www.superbagsmarket.com/mcm-bags-c-15.html
http://www.superbagsmarket.com/fendi-bags-c-16.html
http://www.superbagsmarket.com/mulberry-bags-c-17.html
http://www.superbagsmarket.com/marc-jacobs-bags-c-18.html
http://www.superbagsmarket.com/miu-miu-bags-c-19.html
http://www.superbagsmarket.com/ysl-bags-c-20.html
http://www.superbagsmarket.com/tory-burch-bags-c-21.html
http://www.superbagsmarket.com/givenchy-bags-c-22.html
http://www.superbagsmarket.com/ferragamo-bags-c-23.html
http://www.superbagsmarket.com/lancel-bags-c-24.html
http://www.superbagsmarket.com/loewe-bags-c-25.html
http://www.superbagsmarket.com/tods-bags-c-26.html
http://www.superbagsmarket.com/paul-smith-bags-c-27.html
http://www.superbagsmarket.com/dg-bags-c-28.html
http://www.superbagsmarket.com/alexander-wang-bags-c-29.html
http://www.superbagsmarket.com/bottega-veneta-bags-c-30.html
http://www.superbagsmarket.com/specials.html
http://www.guccishoesuk-2014.com/
http://www.burbagssale2014.com/
http://www.polo-ralphlaurenonline.com/
http://www.thebeatsbydre.net/

Eric Simmons said...

Great and Useful Article.

Online Java Course

Java Online Training

Java Course Online

J2EE training

online J2EE training

Best Recommended books for Spring framework

Java Interview Questions








Java Training Institutes in Chennai

Java Training in Chennai

J2EE Training in Chennai

java j2ee training institutes in chennai

Java Course in Chennai

oakleyses said...

burberry handbags, prada outlet, ray ban sunglasses, gucci handbags, tiffany and co, louis vuitton, christian louboutin outlet, christian louboutin uk, tory burch outlet, ray ban sunglasses, polo ralph lauren outlet online, louis vuitton outlet, jordan shoes, michael kors outlet online, nike air max, christian louboutin, ray ban sunglasses, louis vuitton outlet, longchamp outlet, prada handbags, michael kors outlet online, uggs outlet, christian louboutin shoes, uggs on sale, ugg boots, louis vuitton outlet, chanel handbags, longchamp outlet, oakley sunglasses, nike outlet, louis vuitton, uggs outlet, polo outlet, michael kors outlet, burberry outlet, tiffany jewelry, michael kors outlet online, oakley sunglasses, nike air max, ugg boots, michael kors outlet online, oakley sunglasses, replica watches, nike free, michael kors outlet, replica watches, longchamp outlet, kate spade outlet

oakleyses said...

sac vanessa bruno, hollister uk, polo lacoste, vans pas cher, nike roshe run uk, nike free uk, true religion outlet, air max, polo ralph lauren, coach purses, louboutin pas cher, hollister pas cher, kate spade, lululemon canada, timberland pas cher, michael kors outlet, sac longchamp pas cher, michael kors pas cher, ray ban pas cher, true religion outlet, abercrombie and fitch uk, nike air max uk, replica handbags, nike air max uk, nike blazer pas cher, coach outlet, nike roshe, michael kors, mulberry uk, coach outlet store online, burberry pas cher, guess pas cher, nike air max, sac hermes, michael kors, north face uk, hogan outlet, north face, converse pas cher, oakley pas cher, ralph lauren uk, true religion outlet, new balance, jordan pas cher, nike free run, nike tn, longchamp pas cher, true religion jeans, nike air force, ray ban uk

oakleyses said...

hollister, north face outlet, mac cosmetics, baseball bats, nike huaraches, babyliss, new balance shoes, iphone cases, chi flat iron, louboutin, ferragamo shoes, iphone 5s cases, longchamp uk, soccer shoes, mcm handbags, nike roshe run, timberland boots, mont blanc pens, vans outlet, bottega veneta, instyler, oakley, ralph lauren, valentino shoes, giuseppe zanotti outlet, s6 case, p90x workout, celine handbags, iphone 6s plus cases, herve leger, north face outlet, nike trainers uk, ipad cases, iphone 6s cases, lululemon, wedding dresses, nike air max, abercrombie and fitch, nfl jerseys, hermes belt, insanity workout, ghd hair, asics running shoes, beats by dre, iphone 6 cases, reebok outlet, jimmy choo outlet, soccer jerseys, hollister clothing, iphone 6 plus cases

oakleyses said...

pandora jewelry, canada goose uk, canada goose, barbour, moncler, karen millen uk, swarovski crystal, replica watches, louis vuitton, canada goose, louis vuitton, juicy couture outlet, nike air max, lancel, swarovski, canada goose jackets, gucci, converse, thomas sabo, canada goose outlet, pandora charms, ugg,uggs,uggs canada, juicy couture outlet, doudoune moncler, hollister, moncler, montre pas cher, coach outlet, links of london, hollister, ugg uk, ugg, toms shoes, marc jacobs, pandora uk, vans, canada goose, moncler, canada goose outlet, moncler outlet, moncler outlet, louis vuitton, moncler, ray ban, louis vuitton, louis vuitton, converse outlet, moncler uk, ugg,ugg australia,ugg italia, supra shoes, barbour uk

Post a Comment

 
Copyright 2009 Spring vs Java EE Web Dev. Powered by Blogger Blogger Templates create by Deluxe Templates. WP by Masterplan