REST, Representational State Transfer, is a powerful, lightweight architecture that allows you to work with data in a comprehensive manner via HTTP. Yet, as powerful as REST is, getting it to work with your code can be a bit of a chore without some help. When it comes to coding in Java, Jersey provides the help that you need. Jersey is an open source project that simplifies the work required to adapt your Java code to REST.
In this article I'll give you a lightning fast overview of REST, and explain the basic operational concepts behind Jersey. Then I'll show you how to work with Jersey to make some real world Java code RESTful. Finally I'll show you how to access your RESTful code using browser based JavaScript, AJAX and JSON. As an added topic, I'll show you to inject a Base64 encoded image file onto a web page at run time.
All the code that I use in this article is available for download so that you follow along as you like.
Understanding the Article's Project Code
I am going to teach you the ins and outs of creating a basic Jersey application using a
demonstration project. This demo project is named, CardDealer. CardDealer is a web application that renders a random playing card from a server side shoe of playing cards. You display a random playing card by clicking a "Get Card" button on the project's main web page, as shown in Figure 1 below.
Figure 1: The CardDealer Web App uses AJAX to call a REST Service
(click to view)
Post a commentEmail ArticlePrint ArticleShare ArticlesAlthough this interaction may seem simple, there is a lot of technology going on underneath the hood. Jersey and AJAX play a key role in the interaction.
Stuff You Need To Know
The intention of this article is to get you up and running on REST using Jersey as quickly as possible. I've use the Maven Framework to organize and build the various Java modules that make up the project. Also, I've used Spring to do runtime injection of property values on a Java helper class that is part of the CardDealer project. And, as mentioned above, I've used AJAX to facilitate communication between the client side browser and the server side CardDealer REST code.
Thus, in order to get full benefit from reading this article, it’s helpful to have a basic understanding of the following technologies:
Maven, to define a project's dependencies, build the sample project and run unit tests
Spring, to do runtime property injection
AJAX, to make a XmlHttpRequest back to a web server
JSON, to encapsulate information into a client-side JavaScript object
Yet, if you find yourself needing to brush up on the technologies listed above, don’t fret! This article has a lot of information that you’ll find useful at a conceptual level.
What is REST?
REST is an acronym for Representational State Transfer. REST offers an elegant way to manipulate the HTTP protocol in order to exchange data between computers. The key is the HTTP Request. In the very old days of the Web one thought of using HTTP Requests mostly to get a file from a Web Server.
For example, I'd make an HTML web page that had my profile information on it, store that page as a file, myProfile.html in a directory, BobInfo. Then, others interested in that file would call the URL, http://www.myExampleWebSite.com/BobInfo/myProfile.html. The web server at the other end of the URL would fetch the file and send the file bytes back to the calling computer, either to a browser or some sort of computer based consuming intelligence that can interpret the HTML. Of course, over time things got a lot more complex. Data driven web pages required that web pages be made up on the fly. So, in that more modern world, myProfile.html might not contain HTML that represented my profile information as a hard coded web page. Instead the web server might be configured to interpret HTML files, or more typically, JSP, ASPX or PHP files, as code that contains HTML interspersed with server-side data-driven programming logic to dynamically construct a web page on the fly. Then, the notion of dynamically constructing a page of HTML text gets abandoned altogether. Why not have the web server intelligence create some XML and return that? Why not accept XML as part of an HTTP Request? Why not return a more complex XML structure such as a
SOAP message. In the World Wide Web all things are possible. Thus, over time
HTTPRequests and HTTP
Responses became more complex and unwieldy. And, so it goes... Until REST.
In a REST world things get simpler and a lot more interesting. First and foremost,in REST a URL (or as some purist RESTafarians prefer, a URI) identifies a "thing". You can think of a "thing" as a noun.
For example, a URL, www.CoolCars.com/salesman/reselman/bob can refer to a salesman named Bob Reselman, while another URL, www.CoolCars.com/lenders/contact/reselman/bob can refer to a lender contact named, Bob Reselman. The important thing to understand is that the URL defines a "thing" and that the structure of that definition is defined by the domain being called. (Later on in this article I’ll show you how to use
WADL, Web Application Description Language, to determine how to call things in a given REST domain.)
Okay, so REST tells us that URL defines a thing. The question that arises is what can we do with that thing? Well, we can get the thing from the domain; we can add the thing to the domain or we can delete the thing from the domain. How? This is where the use of the HTTP
METHOD comes into play.
As mentioned above, REST utilizes the HTTP protocol to do very powerful things in a very simple way. One of the features of the HTTP protocol that REST utilizes extensively is the METHOD field. The most commonly known HTTP methods are GET and POST. In the old days, web developers used the
GET and POST value as way for passing some query string and form information to a web server for processing. No biggie.
REST however, takes a much more elegant approach to the use of METHOD fields. REST says, "hey, let's use these methods as they were intended to be used, as directives about the intent of a HTTP Request". Thus, in REST, GET actually means to get some data, PUT means to add data (as does POST), and DELETE means to delete data. There are more HTTP Methods you can use in REST. But, for now let's focus on the basic ones.
So, now you have the basics of REST. REST allows you to define a thing via a URL, and then by setting the METHOD field in the HTTP Request, you can get the thing, add the thing or delete the thing. Of course this means that we are dealing with the HTTP protocol at a lower level than has been usual for most bread and butter web developers. But, once you get the hang of working with essential HTTP, life becomes a lot easier and a lot more powerful.
How does Jersey make REST easier?
So where does Jersey fit in to all of this? Jersey takes care of the lower level HTTP processing referenced above. Jersey provides a way to map a RESTful HTTP Request directly to intelligence in your Java code.
For example, let's say that we have a RESTful URL, http://localhost:9090/card-dealer-rest/rest/card-dealer/card that is sent to a Web server using the HTTP METHOD, GET. Before Jersey came along, in order to process the REST statement we'd do some low level work intercepting the HTTP Request coming into the computer, dissect the URL to determine the thing it represents and then do a whole bunch of programming based on the HTTP METHOD field to create an HTTP Response relevant to the RESTful HTTP Request. This is a lot of work! However, when we use Jersey things get a lot easier.
Please take a look the Jersey enhanced code in Listing 1 below.
Listing 1: Using Jersey annotations to bind a URL to a Java class
01: @Path("/card-dealer")02: public class CardDealerRest {03: //Some Java code follows......04: .05: .06: @GET07: @Produces(MediaType.APPLICATION_JSON)08: @Path("/card")09: public Response getCard(@QueryParam("shoeId") String shoeId) throws IOException, InvalidCardDeckException10: {11: //Some Java code for the method follows......12: .13: .14: .15: return generateResponse(gson.toJson(rc),16: MediaType.APPLICATION_JSON_TYPE);17: }18: //Some more Java code follows......19: .20 .21: //end of class22: }
Notice the use of the Java
annotation, @Path, in line 01 above the declaration for the class, CardDealerRest. @Path is a Jersey annotation that maps a URL segment to a class and then subsequently to methods within the class. In this case of the use of @Path in line 01 above, /card-dealer, is mapped to the class, CardDealerRest. Thus, any HTTP Request that has a URL base of /card-dealer, will, with the help of Jersey, be routed by the web app to an instance Java class, CardDealerRest.
Also notice that line 08 uses @Path to map the subsequent part of the URL, /card, to the method, getCard(). Thus, using Jersey we've taken a RESTful HTTP Request and bound it to a method in a Java class in order to facilitate server-side behavior.
This is pretty much how Jersey works in terms of mapping a URL to code. In your web.xml you define a URL base as an entry point to which the Web server will pass the HTTP Request to the Jersey
servlet. Then you use Jersey @Path annotations to define how the remainder of the URL is to be mapped, first to a class, which in Jersey parlance is called a resource class, and then to a method within the class. Figure 2 below illustrates this concept.
Figure 2: The Jersey @Path annotation maps segments of a URL to a Java class and methods for execution
(click to view)
There are additional Jersey annotations that you use to do things such as declare the mime type that your the methods of the resource will accept, bind an HTTP Request METHOD to a particular method in the resource class and define a return mime type that will be set in HTTP Response.
Table 1 below is an excerpt from the
Sun documentation that describes the basic Jersey annotations.
Table 1: The Jersey Annotations
AnnotationDescription
@Path The @Path annotation's value is a relative URI path indicating where the Java class will be hosted, for example, /helloworld. You can also embed variables in the URIs to make a URI path template. For example, you could ask for the name of a user, and pass it to the application as a variable in the URI, like this, /helloworld/{username}.
@GETThe @GET annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP GET requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@POSTThe @POST annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP POST requests. The behavior of a resource is determined by the HTTP method to which the resource is responding
@PUTThe @PUT annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP PUT requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@DELETEThe @DELETE annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP DELETE requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@HEADThe @HEAD annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP HEAD requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@PathParamThe @PathParam annotation is a type of parameter that you can extract for use in your resource class. URI path parameters are extracted from the request URI, and the parameter names correspond to the URI path template variable names specified in the @Path class-level annotation.
@QueryParamThe @QueryParam annotation is a type of parameter that you can extract for use in your resource class. Query parameters are extracted from the request URI query parameters.
@Consumes The @Consumes annotation is used to specify the MIME media types of representations a resource can consume that were sent by the client.
@ProducesThe @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client, for example, "text/plain".
@ProviderThe @Provider annotation is used for anything that is of interest to the JAX-RS runtime, such as MessageBodyReader and MessageBodyWriter. For HTTP requests, the MessageBodyReader is used to map an HTTP request entity body to method parameters. On the response side, a return value is mapped to an HTTP response entity body using a MessageBodyWriter. If the application needs to supply additional metadata, such as HTTP headers or a different status code, a method can return a Response that wraps the entity, and which can be built using Response.ResponseBuilder.
You can find a full JavaDoc description of Jersey annoations
here.
Tags:
Web services23410 Comments
(click to add your comment)October 9 2009 12:55 PMPDT
Well written!
Reply to this commentOctober 9 2009 3:24 PMPDT
Just got an note from a reader: "You would be better off simply providing the image name, and constructing the image url with JavaScript on the front end to take advantage of the browser caching the image. Also the data prefix wont render images on ie6 or ie7, and a 32k limit on ie8."
Thanks reader!
Interesting, I don't even consider IE any more.
Reply to this commentOctober 14 2009 10:40 AMPDT
Excellent article specially explaining REST and how REST play role with others like Jersey.Keep it up
Reply to this commentOctober 17 2009 10:53 PMPDT
I like your article. It's well written and easy to follow. I'm having trouble with the code. First maven complained about not finding it. I googled and found an answer for that. But then I ran into
[INFO] Failed to resolve artifact.
Missing:
-----------
1) javaee5:javaee5:jar:5.0
I found a post that seemed to say I should add
javaee
javaee-api
5
javax.persistence
persistence-api
1.0
org.glassfish
javaee-api
3.0-Prelude-b28b
provided
I presume to one of the pom.xml files (the top one?) but I this is either wrong or I put in in the wrong place. I know this doesn't really have anything to do with your article but I would appreciate any he
Reply to this commentOctober 20 2009 4:55 PMPDT
Pam, I think that maven is complaining that you do not have Java 1.5 installed in your development environment. Do you?
October 30 2009 11:26 AMPDT
nicely done. the best REST tutorial I've come across.
Reply to this commentNovember 1 2009 2:09 PMPDT
Hi Bob, very nice article. I'm a Maven newbie and like Pam, I'm having trouble with this:
[INFO] Failed to resolve artifact.
Missing:
-----------
1) javaee5:javaee5:jar:5.0
I've opened the project on Netbeans 6.7 with the Glassfish bundle. I see in the parent pom.xml that this is supposed to be a container provided dependency and I've run javaee 5 apps in my current dev environment before but i can't find a javaee5-5.0.jar anywhere ( in my file system or on the web ). Do you have any suggestions? I'm really at a loss as what to do next.
Reply to this commentNovember 1 2009 11:03 PMPDT
nevermind. figured it out.
Reply to this commentJune 15 2010 5:55 AMPDT
nice article regarding REST; but the example should be more easy.
Reply to this commentJuly 9 2010 4:49 PMPDT
One of the key benefits of REST is that a resource is equally easy to consume for a human as it is for a machine. We really tried to drive this home with the open source RESTx ( http://restx.mulesoft.org ) project: It makes the creation and use of RESTful resources really simple and quick, both for client applications as well as users. In fact, users just need to fill out simple forms to create new RESTful resources, while developers can easily develop new data access, integration and processing components in several languages.
Reply to this commentComment and Contribute
Your name/nickname
Your email
XHTML: You can use these tags: <b> <u> <i>