Monday, March 1, 2010

JAX-RS RESTful Web Service - Jersey

Web Services: A software system designed to support Interoperable machine to machine interaction.

SOAP Web Service: SOAP/XML-Based Web Services

  • Complex
  • Exchange Bloat

Restful Web Services (A SOAP Alternative)Why?

  • Still language / platorm independent = interoperability
  • Simpler / Easier - based on well known Web paradigm
    • Bring back the "Web" in Web services.
  • Can be more concise
    • Clients can choose their data format (XML, XHTML, JSON, etc)
  • Cacheable results (WWW paradigm).

SOA vs other-OAs
Comparisions to SOAP-based Web Services may be inappropriate. Both address particular needs.
> SOAP based Web Services are SOA.
> SOA in WS-* form
> An architecture loaded by standards.
> Restful Web Service are REST or Web Oriented Architecture.
> ROA or WOA
> An architecture style
> WOA = SOA + REST + WWW
> Web sites for machines vs Web Sites for humans.

REST = Representation State Transfer
> Term and idea introduced in 2000 in Phd dissertation by Roy Fielding.
> Fielding was a coauthor of HTTP
> Co-founder of Apache HTTP Server project.
> REST concepts originated with WWW and pre-date SOAP Web Services.

Resources:
> At the heart of REST is the concept of a Resource.
> A resource is a thing - anything you can conceive.
> Any coherent and meaningful concept
> You, me , all of us
> An account
> An order
> A stock
> A health record
> A hotel reservation
> book.

Resource = Noun:
RESTful Web Service developers are fond of suggesting resources are typically expressed by nouns.

Representation:
> A representation is a document that captures the current state of a resource.
> For example, an HTML Web page document with information (state) about a book you are interested in.
> So REST is about the transfer (request and response) of respresentation of resources.

URI:
> Each resource must be identified.
> Uniform Resource Identifier (URIs) are used to identify resources.
> More specifically, URL's are used in Web-based REST systems.
> They identify where and what resource is available.
>  http://www.sonianu.com/students/jamesbond


The WWW and REST
> So you are already use REST today!
> When you are browsing the WWW, you request the representation of a resource state via URL
> Resource state like:
> Stock prices for stocks.
> Cost / availability of a room.
> Course catalog from a school
> Typically , you (or more precisely your browser) asks for the representation in the form of 
> HTML
> Images
> Other MIME types


Representation Formats:
> While humans are intersted in browser understood and displayable representations , machines are not.
> Machines are more typically intersted in more structred document representations of resources.
> XML
> HTML
> JavaScript Object Notation (JSON)
> Could even be SOAP (but not usually)
> The type of format of requested representation is often suggested in the REST request URL, eg: http://www.sonianu.com/students/jamesbond/json


REST Verbs:
> When doming Web-based REST, HTTP methods are used to identify what you want done with /to the resource state.
> GET: the most common , suggest the client would like to receive the latest representation of the resource state.
> POST: provides the state for the creation of a new resource
> Typically, the state data is provided in the body of the HTTP POST requst message.
> DELETE: requests the removal of a resource.
> PUT: provides the new state for the update of a resource's state.
> Again, typically , state data is also provided in the body of the HTTP PUT request message.
> RESTful developers akin the HTTP methods to the verbs acting on the nouns (resources).


Some REST Examples
Stock Quote Fetch (XML)
http://ws.cdyne.com/delayedstockquote/delayedstockquote.asmx?GetQuote&StockSymbol=MMM&LicenseKey=0
http://ws.cdyne.com/delayedstockquote/delayedstockquote.asmx?op=GetQuote
GeoName-Country Data fetch
XML: http://ws.geonames.org/countryInfo?country=us
JSON:http://ws.geonames.org/countryinfoJSON?country=us
CSG: http://api.geonames.org/countryInfoCSV?lang=EN&country=US&username=demo&style=full


RESTful Web Services in Java
> Implementaiton Options:
> Servlets
> Roll your own
> Restlet Open Source projects
> JAX-WS
> Was designed to process SOAP message
> Retrofitted to allow most of the SOAP message processing to be by passed. Consider a clumsy and inconvenient solution.
> JAX-RS
> It is relatively recent addition to the Java community. The final release of the specification (JAX-1.0) occourred in Oct 2008.
> JAX-RS maps URIs, HTTP methods and MIME content type negotiation to annotated POJOs.

Jersey:
> A with all Java specification, JAX-RS must be implemented.
> The jersey project (https://jersey.dev.java.net/) is Sun's reference implemenation of JAX-RS 1.0
> Jersey is already part of Glassfish
> Jersey (and by default the JAX-RS specification / API) are part of Java EE 6.
> Jersey is not , however , the only JAX-RS implementation.
> Resteasy is an implemetation of JAX-RS by JBoss.

Jersey Setup:
> As Jersey is not a part of most Java runtime environments at this time, you must first get Jersey and make it a part of your project.
> Download Jersey from http://jersey.dev.java.net/
> The Download includes several Jersey libraries (see the lib folder) to include the Jersey core, core server, Jersey Client, etc.
> Jersey is also dependent on many third party jars too like asm.jar ( a bytecode manipulation framework) and jettison.jar (API which read and write JSON).
> The required JAR files are all in the downloaded zip file.
> With Jersey added to your project, you must add the Jersey adapter Servlet to your web.xml file.
> The adapter servlet route REST traffic to the appropriate RESTful Web Service POJO/JavaBean.
> Open your application's web.xml file and add the following <servlet> element.
<servlet>
<servlet-name>JerseyAdapterServlet</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.test.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
> You must also add a <servlet-mapping> element to map the appropriately designated requests to the servlet and thus to the RESTful WebService beans.
> The URL pattern is up to you, however many developers choose the /resources/* pattern (as shown below) which aligns with the idea of requesting REST resources.
<servlet-mapping>
<servlet-name>JerseyAdapterServlet</servlet-name>
<servlet-class>/resources/*</url-pattern>
</servlet-mapping>
> An additional <init-params> element must also be added to the <servlet> element above.
> However, a better understanding of the RESTful services is needed before adding this element.
JAX-RS Services
> Using JAX-RS, REST resources are POJO.
> The POJOs are annotated with @Path
> @Path takes one argument, the argument identifies the relative request URL path to which the resource responds.
@Path("/helloworld")
public class HelloWorldResource{
...
}
> The @Path annotation and most annotation discussed here can be found in the jaxws.ws.rs package.

RESTful Service Path:
> The URI path to the RESTful POJO is relative to the base URI of the server, context root of the WAR, and the URL pattern for the Jersey adapter servlet.
http://<server>:<port>/<context>/<JerseyServletMapping>/<Path>
> So assuming the POJO was in a MyWebApp War, a URL request to this HelloWorldResource might look like following:
> http://localhost:8080/MyWebApp/resources/helloworld
> Paths are automatically encoded. So a @Path["/hello world"] is the same as @Path("/hello%20world").
> Paths may use wild cards and regular expressions to assist in mapping.

RESTful Operations
> Add annotations (@GET, @POST, @PUT, @DELETE, @HEAD) to the resource methods to indicate what should be invoked for each type of HTTP request.
@Path("/helloworld")
public class HelloWorldResource{
@GET
public String sayHello(){
return "Hello World";
}
}
> Methods that are annotated with @GET, @POST, @PUT, @DELETE and @HEAD are called resource methods.
> These methods must be declared public.
> if a resource methods returns void , the response to the client will be an empty HTTP method body with a 204 status code (request successfully processed).
> By default, the resources return text/plain, However, the @Produces annotation can be used to specify the MIME type of response.
> It can also be placed on the resource methods to overrid any class @Produces setting.

DEMO - RESTFUL DEMO - ECLIPSE

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PATH;
import javax.ws.rs.PathParam;

@Path("/helloworld")
public class HelloWorldResource{
@GET
public String sayHello(){
return "Hello World";
}

@POST
@PATH("{msg}")
public String echoHello(@PathParam("msg") String message) {
return "You said: " + message;
}
}
Installed to Tomcat with Web.xml

@Path("/helloworld")
@Produces("text/html")
public class HelloWorldResource{
@GET @PATH("/text")
//@Produces("text/xml")
public String sayHello(){
return "Hello World";
}

@POST @PATH("{msg}")
@Produces("application/json")
public String echoHello(@PathParam("msg") String message) {

}
}


Representations:
> Resources may also be sent information (as part of the HTTP request body) by the client.
> The @Consumes annotation works in a fashion similar to @Produces but for incoming rather than outgoing MIME types.
> @Consumes specifies which MIME types can be accepted or consumed by the resources.
> Like @Produces , it can be specified on the class or method level (where it overrides the class annotation setting).
> if a resource is unable to consume the MIME type of a client request, the runtime sends back an HTTP 415 error (Unsupported Media Type).
@POST
@Consumes("text/plain")
public void respondToMessage(String message) {
...
}

Path Parameters:
> THe URL path may contain variables. The variables are substitued at runtime in order to provide the resource with additional information.
> Variable are denoted by curly braces in the @Path annotation @Path("/helloworld/{username}")
> Make sure servlet mapping takes into account any extra data passed via the URL parameters. <url-pattern>/resources/*</url-pattern>
> Without the "*" in the url-pattern, the additional data is interpreted as part of the URL causing the request to miss it's intended target resources.
> Regular expressions can be used in the variable declaration to constrain valid character data. @Path("/helloworld/{username:[A-Z][a-A-Z]}")
> In this example, the username must start with an uppercase character and then include any number/anycase of charactes after that.
> If an requset of the resource, the username provided in the URL does not match the regular expression template then a 404 (Not Found) error is the response.
> In other words, sending the wrong data is as good as if the resource is not there.
> If multiple variable are needed, seperate the curly braced variables with a "/". @Path("/helloworld/{firstName}/{lastName}")

Query String Parameters
> Query String parameters can be extraccted with the @QueryParam annotation.
> In a fashion to the use of @PathParam, use the @QueryParam annotation in front of any method parameter.
@Path("/helloworld")
public class HelloWorldResource {
@GET
@Produces("text/plain")
public String sayHello(QueryParam("username") String username) {
return "Hello "+ username;
}
}
> the method parameter will be set to the query string parameter by the same name. http://localhost:8080/MyWebApp/resources/helloworld?username=Anup

Other Parameters:
> In fact there are six type of parameter that you can extract data from using annotation.
> You have already seen path parameters and query parameters.
> In addition , you can extract data from form parameters, cookie parameters, header parameters and matrix parameters using the following annotations.
Parameter JAX-RS Annotation
HTML form parameter @FormParam
HTTP Header parameter @HeaderParam
HTTP Cookie parameter @CookieParam
Matrix URL parameter @MatrixParam


JAX_RS, JAXB and JSON
> The Java architecture for XML Binding (JAXB) allows Java objects to be marshaled and unmarshaled in/out of XML.
> It is used heavily in JAX-WS for SOAP-based Web Services.
> JAXB annotations can be used with JAX-RS to marshal and unmarshal your java types to XML for RESTful Web Services producing or using XML.
> For Eg, consider the following JAXB annotated type.
@XmlRootElement(name="student")
public class Student {
private int id;
private String name;
private String grade;
//getters and setters removed for brevity.
}
> In order to return JAXB produced XML documents of the Student type, simply have your RESTful service produce an instance of that type.
@Path("/students")
public class StudentResource{
@GET
@Produces("application/xml")
public Student getStudent(@QueryParam("id") int studentid) {
Studnet student = // work to retrieve Student object by id
return student;
}
}
> Likewise use any of the parameter annotations with a Student type parameter to have JAX-RS use JAXB to unmarshal XML data into object form.
<student>
<grade>A+</grade>
<id>1</id>
<name>Anup</name>
</student>

> In similar fashion , JAX-RS provides libraries to automatically marshal and unmarshal in JSON format (lighter than XML payload)!
> Just change the @Produces to "application/json" and magically JAX-RS provides the same data in JSON format.
@GET
@Produces("application/json")
public Student getStudent(@QueryParam("id") int studentid) {
Student student = // work to retrieve Student object by id 
return student;
}
> Some of the other JAX-RS implementations support additional representations.
> For example, Resteasy supports Atom.
> {"grade":"A+";"id":"12","name":"Anup"}


Resource Lifecycle:
> By default , ther JAX-RS environment creates an instance of the resource (the JAX-RS POJO) for each request.
> The resource can be configured for two other lifecycles.
> Use the @Singleton annotation on the resource to indicate a single instance should be reused for all resquests.
import com.sun.jersey.spi.resource.Singleton;
@Path("/helloworld")
@Singleton
public class HelloWorldResource {
...
}
> Use @PerSession to indicate that a new instance should be created and reused for each client session.
> It should be noted that these last two annotation are Jersey implementation are not definted in JAX_RS.
> Note the com.sun.jersey package names
import com.sun.jersey.spi.container.servlet.PerSession;
@Path("/helloworld")
@PerSession
public class HelloWorldResource {
...
}

JAX-RS Resource Deployment
> Once you have your JAX-RS resource constructed, you must inform the JAX-RS adapter servlet of your resource.
> There are several options for identifying resources.
> The simplest way is to provide an <init-param> to the Jersey Adapter Servlet.
> The init-param provides the adapter with a list of packages containing JAX-TS anntotated resources.

JAX-RS Clients:
> The JAX-RS specification does not specify how to build a client.
> In Java one could use existing client API such as java.net.URL, URLConnection or HTTPClient.
> Of course since REST operates simply over the web usring HTTP etc, a simple browser can be used to test RESTful service.
> However, many of the JAX-RS implementation provides a Client API.
> The Jersey JAX-RS implementatioon comes with a client API, here is a small sample application to call on the HelloWorldResource.
import javax.ws.rs.core.MultivaluedMap;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;

public class StudentClient {
public static void main(String [] args) throws Exception  {
Client client = Client.create();
WebResource wr = client.resource("http://localhost:8080/MyWebApp/resources/helloworld");
MultivaluedMap qps = new MultivaluedMapImpl();
qps.add("username", "Anup");
String s = wr.queryParams(qps).get(String.class);

System.out.println("Your RESTful Response: "+ s);
}
}
> Jersey's Client Object is the main configuration point for building a RESTful web service client.
> WebResources as its name implies , represents the RESTful resource to the client.
> The client API comes replete with capability to pass all types of parameters and data in the body of the request message and to extract data from the resonse.
> Notice the Jersey packages, Again the client side API is not by specification.

Before Adopting REST - JAX-RS
No REST for the Weary:
> REST is not a standard. REST follows conventions.
> It uses well understood paradigms and standards of the Web (HTTP, URLs etc)
> Your REST may not be my REST.
> Assumes point-to-point communications.
> It is a client / server model.
> Doesn't support distributed computing model well.
> Generally speaking, it's bound to HTTP.
> Fielding's paper didn't say it had to be.
> Supporting WWW infrastructure makes it difficult to use else where.
> Not everyting fits well into GET/POST/... (CRUD) activity.
> REST "Verbs" don't always fit additional application semantics.
> Can be overcome, but not always clean.
> Asynchronous Activity - ???
> Client can send callback location
> Services provide drop ship location
> Transaction - ???
> Security - ???
> HTTPS anyone
> Service Descriptions and Registeries (a la WSDL and UDDI)
> WSDL - Clumsy - Web Service Descriptor Language.
> WADL - Web Application Description Language.






Ques 01: Can you address security in RESTful services?
Ans  01: Security: Since most RESTful Web services rely on HTTP, you can use HTTPS and/or existing HTTP mechanisms to secure your RESTful Web services.  By design, RESTful Web services are lighter-weight that their SOAP counterparts.  Therefore, the kinds of security standards that exist in WS-* specifications are formally available in RESTful settings.  Some RESTful advocates suggest RESTful Web services are actually more secure because they rely on the Internet’s existing security infrastructure

Ques 02: How is Jersey ( JAX_RS)  different than Servlet based REST mechanism like Restlet. I can see Jersey has AdapterServlet too? Is Jersey  based on Servlet too then?
Ans  02: Jersey is an JAX-RS implementation.  RESTlet is a way to provide RESTful services in Java, but it is not guided by any standard.  In JAX-RS, your RESTful resource services are implemented as annotated POJO’s.  In RESTlet, the resource service classes extend ServerResource so some consider this a bit of a burden and intrusive.
The RESTlet group does now have an extension package with allows implements the JAX-RS specification.  See here for more details.
Per part 2 of your question, yes a servlet does act as a controller to route traffic to the appropriate annotated Jersey resource service.  In that way, both RESTlet and Jersey are similar in their reliance of servlet technology.

Ques 03: What is the best way to supply the request=GetCapabilities for REST that one has in SOAP or WMS services to communicate meta-data of REST services?
Ans  03: Many RESTful advocates would say the "conventions" associated with RESTful services makes a capabilities listing unnecessary.  That is, the resource as noun and HTTP method as verb make the services very transparent and easy to work with.

Ques 04: Can we run a rest web service using https protocol?
Ans  04: Yes

Ques 05: How about Spring and REST?
Ans  05: As of Spring 3.0, Spring offers RESTful API, but it is not JAX-RS compliant.  See here for details.  In general, Spring makes use of the annotated MVC controllers to serve as RESTful resources.

Ques 06: Is there a way to override the HTTP return error and give more detail?
Ans  06: Yes – to some extent.  For how to modify the message returned from the Jersey implementation see https://jersey.dev.java.net/nonav/documentation/latest/user-guide.html#d4e410

Ques 07 : is there simple/lightweight authentication capabilities with restful web services?
Ans  07 : Per #1, again nothing formal is provided, but there are some 3rd party packages sprouting up and all the standard Web authentication mechanisms could be used.

README & SOURCE