NOTE: This is the Java version of this article and its companion app. A PHP version is available here.
This is a more in depth version of my previous post on the same topic. The previous article only covered the HTTP GET method for building RESTful services. This article (and its new companion app) provides an example of building a complete RESTful API using the different HTTP methods:
- GET to retrieve and search data
- POST to add data
- PUT to update data
- DELETE to delete data
The application used as an example for this article is a Wine Cellar app. You can search for wines, add a wine to your cellar, update and delete wines.

You can run the application here. The create/update/delete features are disabled in this online version. Use the link at the bottom of this post to download a fully enabled version.
The REST API consists of the following methods:
| Method | URL | Action |
|---|---|---|
| GET | /api/wines | Retrieve all wines |
| GET | /api/wines/search/Chateau | Search for wines with ‘Chateau’ in their name |
| GET | /api/wines/10 | Retrieve wine with id == 10 |
| POST | /api/wines | Add a new wine |
| PUT | /api/wines/10 | Update wine with id == 10 |
| DELETE | /api/wines/10 | Delete wine with id == 10 |
Implementing the API using JAX-RS
JAX-RS makes it easy to implement this API in Java. You simply create a class defined as follows:
package org.coenraets.cellar;
@Path("/wines")
public class WineResource {
WineDAO dao = new WineDAO();
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Wine> findAll() {
return dao.findAll();
}
@GET @Path("search/{query}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Wine> findByName(@PathParam("query") String query) {
return dao.findByName(query);
}
@GET @Path("{id}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Wine findById(@PathParam("id") String id) {
return dao.findById(Integer.parseInt(id));
}
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Wine create(Wine wine) {
return dao.create(wine);
}
@PUT @Path("{id}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Wine update(Wine wine) {
return dao.update(wine);
}
@DELETE @Path("{id}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public void remove(@PathParam("id") int id) {
dao.remove(id);
}
}
Quick look at the JAX-RS annotations used in this class:
- @GET, @POST, @PUT, @DELETE: HTTP method the class method responds to.
- @Path: path the method responds to.
- @Consumes: type of data the method can take as input. The data will automatically be deserialized into a method input parameter. For example, you can pass a wine object to the addWined() method either as JSON or XML. The JSON or XML representation of a new wine is automatically deserialized into the Wine object passed as an argument to the method.
- @Produces: One or more response content type(s) the method can generate. The method’s return value will be automatically serialized using the content type requested by the client. If the client didn’t request a specific content type, the first content type listed in the @Produces annotation will be used. For example, if you access http://coenraets.org/rest/wines, you get a list of wines represented as JSON because it is the first content type listed in the @Produces annotation of the findAll() method.
The jQuery client below sends data to the server using JSON (addWine() and updateWine() methods).
The approach you use to actually retrieve the data is totally up to you. In this example, I use a simple DAO, but you can of course use your own data access solution.
Testing the API using cURL
If you want to test your API before using it in a client application, you can invoke your REST services straight from a browser address bar. For example, you could try:
- http://localhost:8080/cellar/rest/wines
- http://localhost:8080/cellar/rest/wines/search/Chateau
- http://localhost:8080/cellar/rest/wines/5
You will only be able to test your GET services that way, and even then, it doesn’t give you full control to test all the content types your API can return.
A more versatile solution to test RESTful services is to use cURL, a command line utility for transferring data with URL syntax.
For example, using cURL, you can test the Wine Cellar API with the following commands:
- Get all wines returned as default content type:
curl -i -X GET http://localhost:8080/cellar/rest/wines
- Get all wines returned as xml:
curl -i -X GET http://localhost:8080/cellar/rest/wines -H 'Accept:application/xml'
- Get all wines with ‘chateau’ in their name:
curl -i -X GET http://localhost:8080/cellar/rest/wines/search/chateau
- Get wine #5:
curl -i -X GET http://localhost:8080/cellar/rest/wines/5
- Delete wine #5:
curl -i -X DELETE http://localhost:8080/cellar/rest/wines/5
- Add a new wine:
curl -i -X POST -H 'Content-Type: application/json' -d '{"name": "New Wine", "year": "2009"}' http://localhost:8080/cellar/rest/wines - Modify wine #27:
curl -i -X PUT -H 'Content-Type: application/json' -d '{"id": "27", "name": "New Wine", "year": "2010"}' http://localhost:8080/cellar/rest/wines/27
The jQuery Client
Accessing your API through cURL is cool, but there is nothing like a real application to put your API to the test. So the source code (available for download at the end of this post) includes a simple jQuery client to manage your wine cellar.
Here is the jQuery code involved in calling the services:
function findAll() {
$.ajax({
type: 'GET',
url: rootURL,
dataType: "json", // data type of response
success: renderList
});
}
function findByName(searchKey) {
$.ajax({
type: 'GET',
url: rootURL + '/search/' + searchKey,
dataType: "json",
success: renderList
});
}
function findById(id) {
$.ajax({
type: 'GET',
url: rootURL + '/' + id,
dataType: "json",
success: function(data){
$('#btnDelete').show();
renderDetails(data);
}
});
}
function addWine() {
console.log('addWine');
$.ajax({
type: 'POST',
contentType: 'application/json',
url: rootURL,
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert('Wine created successfully');
$('#btnDelete').show();
$('#wineId').val(data.id);
},
error: function(jqXHR, textStatus, errorThrown){
alert('addWine error: ' + textStatus);
}
});
}
function updateWine() {
$.ajax({
type: 'PUT',
contentType: 'application/json',
url: rootURL + '/' + $('#wineId').val(),
dataType: "json",
data: formToJSON(),
success: function(data, textStatus, jqXHR){
alert('Wine updated successfully');
},
error: function(jqXHR, textStatus, errorThrown){
alert('updateWine error: ' + textStatus);
}
});
}
function deleteWine() {
console.log('deleteWine');
$.ajax({
type: 'DELETE',
url: rootURL + '/' + $('#wineId').val(),
success: function(data, textStatus, jqXHR){
alert('Wine deleted successfully');
},
error: function(jqXHR, textStatus, errorThrown){
alert('deleteWine error');
}
});
}
// Helper function to serialize all the form fields into a JSON string
function formToJSON() {
return JSON.stringify({
"id": $('#id').val(),
"name": $('#name').val(),
"grapes": $('#grapes').val(),
"country": $('#country').val(),
"region": $('#region').val(),
"year": $('#year').val(),
"description": $('#description').val()
});
}
Download the Source Code
The source code for this application is hosted on GitHub here. And here is a quick link to the project download (Eclipse Dynamic Web Project). It includes both the Java and jQuery code for the application.
UPDATE (1/11/2012): A version of this application using Backbone.js at the client-side is also available on GitHub here. You can find more information on the Backbone.js of this application here.
I’m interested in your feedback. Let me know what you think and what your experience has been building RESTful-based applications using Java and jQuery.
The best Jersey Rest + JQuery example i´ve seen so far… still searching for an easy solution to solve the “cross-site” – problem… some of yours have any idea what to change on server-side in case of running the JQuery – Client on a different webserver? (eg. webservice is running on http://10.10.10.1:8080/cellar, JQuery – client is running on http://10.10.20.1:8080/index.html)
Hi Gerd
I’ve been running into the cross-site problem aswel and after a lot of research found a few solutions:
- JSON-P can be used for GET requests ONLY. Also note that it is not very secure.
- CORS is probably the best way other then using a proxy. (Basically you add the correct headers to your requests and replies.)
Hope this helps.
Cheers
Kenny
Hi,
“(Basically you add the correct headers to your requests and replies.)”
below is an example how to add the header to your response:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getFooBar() {
String json = “”{foo: \”bar\”}”;
return Response.ok(json).header(“Access-Control-Allow-Origin”, “*”).build();
}
Hi Alex, I’have a problem Access-Control-Allow-Origin, and your comment was very ussefull for me!
Regards
Note: sorry for my english
Hi Christophe. As always, a great sample! How would you work the authentication and the security layer on the REST?
How would you work the login in html, and assure that all REST invocations are validated and are secure?
Regards
Hi,
At first let me thank you for putting the nicest example of Webservice that is done using REST/Jersey.
However, my question is not regarding the service, but in database connectivity. You have used mysql as your database and so on, I would like to use Oracle, but the problem with the connection string,
my database name is, Orcl, name: system and password: sa1234, but don’t what would be the syntax for putting the data.
Hi,
At first let me thank you for putting the nicest example of Webservice that is done using REST/Jersey.
However, my question is not regarding the service, but in database connectivity. You have used mysql as your database and so on, I would like to use Oracle, but the problem with the connection string,
my database name is, Orcl, name: system and password: sa1234, but don’t what would be the syntax for putting the data. Can you please share your thoughts, how i can use Oracle database connectivity in your code.
Awesome Example !!!!!! Helped me a lot … Thanks,Thanks,Thanks,Thanks. :-)
Hi,
Thanks for a simple and elegant example for RESTful service. I have one question,
what if the ‘Wine’ object is modified later and a group of people need the initial version of ‘Wine’ and a different group need the newer version of ‘Wine’?
Bottomline, how to deal with versions of ‘Wine’ object? I hate to use query params, that may not be valid for POST, I might use PUT instead, still not an elegant solution.
Your advise please.
Thanks much,
Tamil
Really good article. Thanks for this article and the source code. The example application worked like a charm.
I can’t make this example run beyond the static index.html and main.js. I tried in Eclipse and then in NetBeans with both Tomcat and Glassfish. There seems to some errors in terms of URIs for the RESTFul Webservices. Context was not setup in Glassfish and Tomcat is also not going any further.
I like the example and there is no compilation errors but some how it needs a lot of work around to make it run end to end.
I deployed to tomcat, and no data populated the web page.
Did I dod something wrong?
Bit of a simple question, but how do you open the java project in eclipse (do I need to create a project and import the files)
thanks
Nick
Ahaa, its nice discussion on the topic of this piece of writing at this place at this blog,
I have read all that, so now me also commenting at this place.
Good Job Christophe :)… I am waiting Your article about security concerns about REST/JSON
Hi,
I am a newbie to jquery and I tried the eclipse project and configure my database as defined in the readme file.
But while creating a ‘New Wine’ i got this error “addWine error: error”. Need help…
Awesome tutorial, thank you!
Thanks for providing this example and the example looks nice. But I am able to get the proper output when I use get or delete. But for post or put I am getting problem. When I send the json form using, json.stringify(), the service is not taking up the json, I am sending and I am getting an error message. Can someone who has run this successfully help me send me the code with which he is successful? Thanks in advance,
I have managed to workout the needful to get the example working. But I needed to make some modifications. Thanks for providing this example.
really appreciate the code especially for new beginner like me…thanks alot
Hi,
I have a problem with fields on the DB that contain the underscore “_” character in the field name.
Jersey seems to ignore those fields and no data is stored on the DB …
Any suggestion ?
Hi Christophe, the code highlighter doesn’t work properly on the entire website including all ther posts, wanted to let you know.
Nice post.
If you wanted to have a slightly more ‘RESTful’ API you could implement the search functionality with query params on the Wine resource like so:
/api/wines?name=*Chateau*
Style wise /api/wines/search is more of an RPC approach then a RESTful one.
Thanks for the great tutorial! I have a quick question though, how are the js files and html files being loaded into the browser? Setting the src of the is caught by the servlet and prepends the request for the resources.
Hi Christophe ,
Thanks a lot for the wonderful article. However, i have a question. when I issue a POST using the curl command that you have listed, it gives me a HTTP 1.1 404 Not Found error. Can you kindly have a look into this and let me know.
Thanks again for this wonderful tutorial.
Regards,
Jack
Great example. Helped me a lot in doing a restful service application
It works! Simple and clear!
Thanks!
is it possible to send custom object as a @Pathparam using get method and i need json as output using RESTFUL.
I mean instead of sending all the parameters URI like —-> custom/1/aaa/addr shall we custom/pojo
Client Side:
class Pojo{
int id=1;
String name=”aaa”;
String addr=”addr”;
//setter & getters
}
Main class:
public static void main(String… a)
{
Pojo pojo = new Pojo();
System.out.println(service.path(“rest”).path(“custom/pojo”).accept(MediaType.APPLICATION_JSON).get(String.class));
}
server side:
@Path(“/custom”)
class Custom
{
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path(“{pojo}”)
public Pojo getJsonOutput(@PathParam(“pojo”) Pojo p) {
if(1==p.getId() && “aaa”.equals(p.getName()) && “addr”.equals(p.getAddr())
return new Pojo();
else
return null;
}
}
class Pojo{
int id=1;
String name=”aaa”;
String addr=”addr”;
String firstName=”aaa”;
String lastName=”bbb”;
String firstAddr=”ccc”;
String lastAddr=”ddd”;
String mobnumber=”123457896″;
//Setters & Getters
}
Hi, nice t utorial. But my request is can u provide this example using spring3. I am gladful if u give me spring 3 hibernate mysql restful webservices (jquery and javascript not necessary)
Excellent tutorial, really good for those who have everything in place but need an example that plugs it all together
I got this web site from my pal who told me about this site and at the moment this
time I am browsing this site and reading very informative articles here.
Hello mates, nice post and fastidious urging commented here, I am actually enjoying by these.
Hi im not sure but how can I implement MVC with rest? can I use push or pull?
Thanks in advance
Can I perform partial updates to the Wine object?
For example: return JSON.stringify({
“id”: $(‘#id’).val(),
“name”: $(‘#name’).val(),
“grapes”: $(‘#grapes’).val()
});
Hi All ,
Is there any way to pass multiple json objects from jquery to call a rest service method that has multiple parameter.
eg :
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Wine compareWine(Wine wine1 , Wine wine2) {
return dao.create(wine1);
}
Thank you, for your tutorial. I am using jquery dataTables, how can I persuade Jersey to provide data in a format like this:
{ “aaData”: [
[ "A", "Internet Explorer 4.0", "Win 95+", 4, "X" ],
[ "B", "Internet Explorer 5.0", "Win 95+", 5, "C" ] ] }
which is the format that dataTables requires.
It’s impressive that you are getting ideas from this article as well as from our dialogue made at this place.
It’s really a nice and useful piece of info. I’m
glad that you simply shared this useful information with us.
Please keep us up to date like this. Thanks for sharing.
I don’t know if it’s just me or if perhaps everybody else experiencing issues with your blog.
It appears like some of the text on your posts are running off the screen.
Can somebody else please provide feedback and let me know if this is
happening to them as well? This could be a problem with
my browser because I’ve had this happen before. Appreciate it
Fantastic blog! Do you have any suggestions for aspiring writers?
I’m planning to start my own blog soon but I’m a little lost on
everything. Would you advise starting with a free platform
like WordPress or go for a paid option? There are so many choices out there that I’m totally confused .. Any recommendations? Many thanks!
My relatives always say that I am wasting my time here at
net, except I know I am getting familiarity everyday by reading
such good content.
Hello, just wanted to mention, I enjoyed this article.
It was inspiring. Keep on posting!
Can you please guide me how can I place the Jersey implementation JAR’s out of the project? I mean can I place these jars on a common path for all the JAX-RS web services I have?
its a beautiful example ….. tests r running great but i m unable 2 run the Jquery client … is there any errors… i m not geting the list of wines … help wud b apppreciable
Truly no matter if someone doesn’t know afterward its up to other viewers that they will assist, so here it occurs.