jersey-spring-logo

Tutorial – REST API design and implementation in Java with Jersey and Spring

Looking to REST in Java? Then you’ve come to the right place, because in the blog post I will present you how to “beautifully” design a REST API and also, how to implement it in Java with the Jersey framework. The RESTful API developed in this tutorial will demonstrate a complete Create,_read,_update_and_delete (CRUD) functionality for podcast resources stored in a MySql database.

Contents

1. The example

1.1. Why?

Before we start, let me tell you why I’ve written this post – well, my intention is to offer in the future a REST API for Podcastpedia.org. Of course I could use Spring’s own REST implementation, as I currently do for the AJAX calls, but I wanted also to see how the “official” implementation looks like. So, the best way to get to know the technology is to build a prototype with it. That is what I did and what I am presenting here, and I can say that I am pretty damn satisfied with Jersey. Read along to understand why!!!

Note: You can visit my post Autocomplete search box with jQuery and Spring MVC to see how Spring handles REST requests.

1.2. What does it do?

The resource managed in this tutorial are podcasts. The REST API will allow creation, retrieval, update and deletion of such resources.

1.3. Architecture and technologies

Architecture diagram

The demo application uses a multi-layered architecture, based on the “Law of Demeter (LoD) or principle of least knowledge”[16]:

  • the first layer is the REST support implemented with Jersey, has the role of a facade and delegates the logic to the business layer
  • the business layer is where the logic happens
  • the data access layer is where the communcation with the pesistence storage (in our case the MySql database) takes place

A few words on the technologies/frameworks used:

1.3.1. Jersey (Facade)

The Jersey RESTful Web Services framework is open source, production quality, framework for developing RESTful Web Services in Java that provides support for JAX-RS APIs and serves as a JAX-RS (JSR 311 & JSR 339) Reference Implementation.

1.3.2. Spring (Business layer)

I like glueing stuff together with Spring, and this example makes no exception. In my opinion there’s no better way to make POJOs with different functionalities. You’ll find out in the tutorial what it takes to integrate Jersey 2 with Spring.

1.3.3. JPA 2 / Hibernate (Persistence layer)

For the persistence layer I still use a DAO pattern, even though for implementing it I am using JPA 2, which, as some people say, should make DAOs superfluous (I, for one, don’t like my service classes cluttered with EntityManager/JPA specific code). AS supporting framework for JPA 2 I am using Hibernate.

See my post Java Persistence Example with Spring, JPA2 and Hibernate for an interesting discussion around persistence thema in Java.

1.3.4. Web Container

Everything gets packaged with Maven as a .war file and can be deployed on any web container – I used Tomcat and Jetty but, it could also be Glassfih, Weblogic, JBoss or WebSphere.

1.3.5. MySQL

The sample data is stored in a MySQL table:

database schema

1.3.6. Technology versions

  1. Jersey 2.9
  2. Spring 4.0.3
  3. Hibernate 4
  4. Maven 3
  5. Tomcat 7
  6. Jetty 9
  7. MySql 5.6

Note: The main focus in the post will be on the REST api design and its implementation with the Jersey JAX-RS implementation, all the other technologies/layers are considered as enablers.

1.4. Source code

The source code for the project presented here is available on GitHub, with complete instructions on how to install and run the project:

2. Configuration

Before I start presenting the design and implementation of the REST API, we need to do a little configuration so that all these wonderful technologies can come and play together

2.1. Project dependencies

The Jersey Spring extension must be present in your project’s classpath. If you are using Maven add it to the pom.xml file of your project:

Note: The jersey-spring3.jar, uses its own version for Spring libraries, so to use the ones you want (Spring 4.0.3.Release in this case), you need to exclude these libraries manually.

Code alert: If you want to see what other dependencies are needed (e.g. Spring, Hibernate, Jetty maven plugin, testing etc.) in the project you can have a look at the the complete pom.xml file available on GitHub.

2.2. web.xml

2.2.1. Jersey-servlet

Notice the Jersey servlet configuration [lines 18-33]. The javax.ws.rs.core.Application class defines the components (root resource and provider classes,) of the JAX-RS application. I used ResourceConfig, which is Jersey’s own implementation of the class Application, and which provides advanced capabilites to simplify registration of JAX-RS components. Check out the JAX-RS Application Model in the documentation for more possibilities.

My implementation of the ResourceConfig class, org.codingpedia.demo.rest.RestDemoJaxRsApplication, registers application resources, filters, exception mappers and feature :

Please note the

  • org.glassfish.jersey.server.spring.scope.RequestContextFilter, which is a Spring filter that provides a bridge between JAX-RS and Spring request attributes
  • org.codingpedia.demo.rest.resource.PodcastsResource, which is the “facade” component that exposes the REST API via annotations and will be thouroughly presented later in the post
  • org.glassfish.jersey.jackson.JacksonFeature, which is a feature that registers Jackson JSON providers – you need it for the application to understand JSON data
2.1.2.2. Spring application context configuration

The Spring application context configuration is located in the classpath under spring/applicationContext.xml:

Nothing special here, it just defines the beans that are needed throughout the demo application (e.g. podcastsResource which is the entry point class for our REST API).

3. The REST API (design & implementation)

3.1. Resources

3.1.1. Design

As mentioned earlier, the demo application manages podcasts, which represent the resource in our REST API. Resources are the central concept in REST and are characterized by two main things:

  • each is referenced with a global identifier (e.g. a URI in HTTP).
  • has one or more representations, that they expose to the outer world and can be manipulated with (we’ll be working mostly with JSON representations in this example)

Resources are usually represented in REST by nouns (podcasts, customers, user, accounts etc.) and not verbs (getPodcast, deleteUser etc.)

The endpoints used throughout the tutorial are :

  • /podcasts(notice the plural) URI identifying a resource representing a collection of podcasts
  • /podcasts/{id} – URI identifying a podcast resource, by the podcast’s id

3.1.2. Implementation

For the sake of simplicity, a podcast will have only the following properties:

  • id – uniquely identifies the podcast
  • feed – url feed of the podcast
  • title – title of the podcast
  • linkOnPodcastpedia – where you can find the podcast on Podcastpedia.org
  • description – a short description of the podcast

I could have used only one Java class for the representation of the podcast resource in the code, but in that case the class and its properties/methods would have gotten cluttered with both JPA and XML/JAXB/JSON annotations. I wanted to avoid that and I used two representations which have pretty much the same properties instead:

  • PodcastEntity.java – JPA annotated class used in the DB and business layers
  • Podcast.java – JAXB/JSON annotated class used in the facade and business layers

Note: I am still trying to convince myself that this is the better approach, so if you have a suggestion on this please leave a comment.

The Podcast.java classs look something like the following:

and translates into the following JSON representation, which is actually the de facto media type used with REST nowadays:

Even though JSON is becoming more and more the preffered representation in REST APIs, you shouldn’t neglect the XML representation, as most of the systems still use XML format for communication with other parties.

The good thing is that in Jersey you can kill two rabbits with one shot – with JAXB beans (as used above) you will be able to use the same Java model to generate JSON as well as XML representations. Another advantage is simplicity of working with such a model and availability of the API in Java SE Platform.

Note: Most of the methods defined in this tutorial will produce and consume also the application/xml media type, with application/json being the preferred way.

3.2. Methods

Before I present you the API, let me to tell you that

  • Create = POST
  • Read = GET
  • Update = PUT
  • Delete = DELETE

and is not a strict 1:1 mapping. Why? Because you can also use PUT for Creation and POST for Update. This will be explained and demonstrated in the coming paragraphs.

Note: For Read and Delete it is pretty clear, they map indeed one to one with the GET and DELETE HTTP operations. Anyway REST is an architectural style, is not a specification and you should adapt the architecture to your needs, but if you want to make your API public and have somebody willing to use it, you should follow some “best practices”.

As already mentioned the PodcastRestResource class is the one handling all the rest requests:

Notice the @Path("/podcasts") before the class definition – everything related to podcast resources will occur under this path. The @Path annotation’s value is a relative URI path. In the example above, the Java class will be hosted at the URI path /podcasts. The PodcastService interface exposes the business logic to the REST facade layer.

Code alert: You can find the entire content of the class on GitHub – PodcastResource.java. We’ll be going through the file step by step and explain the different methods corresponding to the different operations.

3.2.1. Create podcast(s)

3.2.1.1. Design

While the “most known” way for resource creation is by using POST, As mentioned before to create a new resource I could use both the POST and PUT methods, and I did just that:

  Description   URI   HTTP method
  HTTP Status response
 Add new podcast  /podcasts/

POST

201 Created

 Add new podcast (all values must be sent)  /podcasts/{id}

PUT

201 Created

The big difference between using POST (not idempotent)

“The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line[…] If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header” [1]

and PUT (idempotent)

“The PUT method requests that the enclosed entity be stored under the supplied Request-URI […] If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response.” [1]

, is that for PUT you should know beforehand the location where the resource will be created and send all the possible values of the entry.

3.2.1.2. Implementation
3.2.1.2.1. Create a single resource with POST

Annotations

  • @POST – indicates that the method responds to HTTP POST requests
  • @Consumes({MediaType.APPLICATION_JSON}) – defines the media type, the method accepts, in this case "application/json"
  • @Produces({MediaType.TEXT_HTML}) – defines the media type) that the method can produce, in this case "text/html".

Response

  • on success: text/html document, with a HTTP status of 201 Created, and a Location header specifying where the resource has been created
  • on error:
    • 400 Bad request if not enough data is provided
    • 409 Conflict if on the server side is determined a podcast with the same feed exists
3.2.1.2.2. Create a single resource (“podcast”) with PUT

This will be treated in the Update Podcast section below.

3.2.1.2.3. Bonus – Create a single resource (“podcast”) from form

Annotations

    • @POST – indicates that the method responds to HTTP POST requests
    • @Consumes({MediaType.APPLICATION_FORM_URLENCODED})– defines the media type, the method accepts, in this case"application/x-www-form-urlencoded"
      • @FormParam – present before the input parameters of the method, this annotation binds the value(s) of a form parameter contained within a request entity body to a resource method parameter. Values are URL decoded unless this is disabled using the Encoded annotation
  • @Produces({MediaType.TEXT_HTML}) – defines the media type that the method can produce, in this case “text/html”. The response will be a html document, with a status of 201, indicating to the caller that the request has been fulfilled and resulted in a new resource being created.

Response

  • on success: text/html document, with a HTTP status of 201 Created, and a Location header specifying where the resource has been created
  • on error:
    • 400 Bad request if not enough data is provided
    • 409 Conflict if on the server side is determined a podcast with the same feed exists

3.2.2. Read podcast(s)

3.2.2.1. Design

The API supports two Read operations:

  • return a collection of podcasts
  • return a podcast identified by id
 Description  URI  HTTP method
 HTTP Status response
 Return all podcasts  /podcasts/?orderByInsertionDate={ASC|DESC}&numberDaysToLookBack={val}

GET

200 OK

 Add new podcast (all values must be sent)  /podcasts/{id}

GET

200 OK

Notice the query parameters for the collection resource – orderByInsertionDate and numberDaysToLookBack. It makes perfect sense to add filters as query parameters in the URI and not be part of the path.

3.2.2.2. Implementation
3.2.2.2.1. Read all podcasts (“/”)

Annotations

  • @GET – indicates that the method responds to HTTP GET requests
  • @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) – defines the media type) that the method can produce, in this case either "application/json" or "application/xml"(you need the @XmlRootElement in front of the Podcast class ). The response will be a list of podcasts either in JSON or XML format.

Response

  • list of podcasts from the database and a HTTP Status of 200 OK
3.2.2.2.1. Read one podcast

Annotations

  • @GET – indicates that the method responds to HTTP GET requests
  • @Path("{id}") – identifies the URI path that the class method will serve requests for. The “id” value is an embedded variable making an URI path template. It is used in combination with the @PathParam variable.
    • @PathParam("id") – binds the value of a URI template parameter (“id”) to the resource method parameter. The value is URL decoded unless this is di sabled using the @Encoded annotation. A default value can be specified using the @DefaultValue annotation.
  • @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) – defines the media type) that the method can produce, in this case "application/json" or "application/xml"(you need the @XmlRootElement in front of the Podcast class ).

Response

  • on success: requested podcast with a 200 OK HTTP status. The format is either xml or JSON, depending on the Accept -header’s value sent by the client (might bet application/xml or application/json)
  • on error: 404 Not found if the podcast with the given id does not exist in the database

3.2.3. Update podcast

3.2.3.1. Design
Description URI HTTP method
HTTP Status response
 Update podcast (fully)  /podcasts/{id}

PUT

200 OK

 Update podcast (partially)  /podcasts/{id}

POST

200 OK

In the REST arena you will be doing two kind of updates:

  1. full updates – that is where you will provide all the
  2. partial updates – when only some properties will be sent over the wire for update

For full updates, it’s pretty clear you can use the PUT method and you are conform the method’s specification in the RFC 2616.

Now for the partial update there’s a bunch of proposals/debate on what to use:

  1. via PUT
  2. via POST
  3. via PATCH

Let me tell why I consider the first option (with PUT) is a NO GO. Well, accordingly to the specification

If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server.“[1]

if I would like to update just the title property of the podcast with the id 2

then, accordingly to the specification the resource “stored” at the location should have only id and title, and clearly my intent was not that.

The second option via POST… well we can “abuse” this one and that is exactly what I did in the implementation, but it does not seem conform to me, because the spec for POST states:

The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.“[1]

That does not look like a partial update case to me…

The third option is to use PATCH,  and I guess this is the main reason the method came to life:

“Several applications extending the Hypertext Transfer Protocol (HTTP)
   require a feature to do partial resource modification.  The existing
   HTTP PUT method only allows a complete replacement of a document.
   This proposal adds a new HTTP method, PATCH, to modify an existing
   HTTP resource.”[2]

I am pretty sure this will be used in the future for partial updates, but since is not yet part of the specification and not yet implemented in Jersey I chose to use the second option with POST for this demo. If you really want to implement partial update in Java with the PATCH check out this post  – Transparent PATCH support in JAX-RS 2.0

3.2.3.1. Implementation
3.2.3.1.1. Full Update

Annotations

  • @PUT – indicates that the method responds to HTTP PUT requests
  • @Path("{id}") – identifies the URI path that the class method will serve requests for. The “id” value is an embedded variable making an URI path template. It is used in combination with the @PathParam variable.
    • @PathParam("id") – binds the value of a URI template parameter (“id”) to the resource method parameter. The value is URL decoded unless this is di sabled using the @Encoded annotation. A default value can be specified using the @DefaultValue annotation.
  • @Consumes({MediaType.APPLICATION_JSON}) – defines the media type, the method accepts, in this case "application/json"
  • @Produces({MediaType.TEXT_HTML}) – defines the media type) that the method can produce, in this case “text/html”.

will be a html document containing different messages and stati depending on what action has been taken

Respsonse

  • on creation
    • on success: 201 Created and in the Location header the specified location where the resource was created
    • on error: 400 Bad request if the minimum required properties are not provided for insertion
  • on full update
    • on success: 200 OK
    • on error: 400 Bad Request if not all properties are provided
3.2.3.1.2. Partial Update

Annotations

  • @POST – indicates that the method responds to HTTP POST requests
  • @Path("{id}") – identifies the URI path that the class method will serve requests for. The “id” value is an embedded variable making an URI path template. It is used in combination with the @PathParam variable.
    • @PathParam("id") – binds the value of a URI template parameter (“id”) to the resource method parameter. The value is URL decoded unless this is di sabled using the @Encoded annotation. A default value can be specified using the @DefaultValue annotation.
  • @Consumes({MediaType.APPLICATION_JSON}) – defines the media type, the method accepts, in this case "application/json"
  • @Produces({MediaType.TEXT_HTML}) – defines the media type) that the method can produce, in this case "text/html".

Response

  • on success: 200 OK
  • on error: 404 Not Found, if there is no resource anymore available at the provided location

3.2.4. Delete podcast

3.2.4.1. Design
Description URI HTTP method
HTTP Status response
 Removes all podcasts  /podcasts/

DELETE

204 No content

 Removes podcast at the specified location  /podcasts/{id}

DELETE

204 No content

3.2.4.2. Implementation
3.2.4.2.1. Delete all resources

Annotations

  • @DELETE – indicates that the method responds to HTTP DELETE requests
  • @Produces({MediaType.TEXT_HTML}) – defines the media type that the method can produce, in this case “text/html”.

Response

  • The response will be a html document, with a status of 204 No content, indicating to the caller that the request has been fulfilled.
3.2.4.2.2. Delete one resource

Annotations

  • @DELETE – indicates that the method responds to HTTP DELETE requests
  • @Path("{id}") – identifies the URI path that the class method will serve requests for. The “id” value is an embedded variable making an URI path template. It is used in combination with the @PathParam variable.
    • @PathParam("id") – binds the value of a URI template parameter (“id”) to the resource method parameter. The value is URL decoded unless this is di sabled using the @Encoded annotation. A default value can be specified using the @DefaultValue annotation.
  • @Produces({MediaType.TEXT_HTML}) – defines the media type that the method can produce, in this case “text/html”.

Response

  • on success: if the podcast is removed a 204 No Content success status is returned
  • on error: podcast is not available anymore and status of 404 Not found is returned

4. Logging

Every request’s path and the response’s entity will be logged when the logging level is set to DEBUG. It is developed like a wrapper, AOP-style functionality with the help of Jetty filters.

See my post How to log in Spring with SLF4J and Logback for more details on the matter.

5. Exception handling

In case of errros, I decided to response with unified error message structure.  Here’s an example how an error response might look like:

A detailed explanation of how errors are handled in the REST api, you can find in the following post Error handling in REST API with Jersey

5.1. Custom Reason Phrase in HTTP status error message response with JAX-RS (Jersey)

If for some reason you need to produce a custom Reason Phrase in the HTTP status response delivered when an error occurs than you might want to check the following post

http://www.codingpedia.org/ama/custom-reason-phrase-in-http-status-error-message-response-with-jax-rs-jersey/

6. Add CORS support on the server side

I extended the capabilities of the API developed for the tutorial to support Cross-Origing Resource Sharing (CORS) on the server side.

Please see my post How to add CORS support on the server side in Java with Jersey for more details on the matter.

7. Testing

7.1. Integration tests in Java

To test the application I will use the Jersey Client and execute requests against a running Jetty server with the application deployed on it. For that I will use the Maven Failsafe Plugin.

7.1.1. Configuration

7.1.1.1 Jersey client dependency

To build a Jersey client the jersey-client jar is required in the classpath. With Maven you can add it as a dependency to the pom.xml file:

7.1.1.2. Failsafe plugin

The Failsafe Plugin is used during the integration-test and verify phases of the build lifecycle to execute the integration tests of the application. The Failsafe Plugin will not fail the build during the integration-test phase thus enabling the post-integration-test phase to execute.
To use the Failsafe Plugin, you need to add the following configuration to your pom.xml

7.1.1.2. Jetty Maven Plugin

The integration tests will be executed against a running jetty server, that will be started only for the execution of the tests. For that you have to configure the following executionin the jetty-maven-plugin:

Note: In the pre-integration-test phase the Jetty server will be started, after stopping any running instance to free up the port, and in the post-integration-phase it will be stopped. The scanIntervalSeconds has to be set to 0, and daemon to true.

Code alert: Find the complete pom.xml file on GitHub

7.1.2. Build the integration tests

I am using JUnit as the testing framework. By default, the Failsafe Plugin will automatically include all test classes with the following wildcard patterns:

  • "**/IT*.java" – includes all of its subdirectories and all java filenames that start with “IT”.
  • "**/*IT.java" – includes all of its subdirectories and all java filenames that end with “IT”.
  • "**/*ITCase.java" – includes all of its subdirectories and all java filenames that end with “ITCase”.

I have created a single test class – RestDemoServiceIT – that will test the read (GET) methods, but the procedure should be the same for all the other:

Note:

  • I had to register the JacksonFeature for the client too so that I can marshall the podcast response in JSON format – response.readEntity(Podcast.class)
  • I am testing against a running Jetty on port 8888 – I will show you in the next section how to start Jetty on a desired port
  • I am expecting a 200 status for my request
  • With the help org.codehaus.jackson.map.ObjectMapper I am displaying the JSON response pretty formatted

7.1.3. Running the integration tests

The Failsafe Plugin can be invoked by calling the verify phase of the build lifecycle.

To start jetty on port 8888 you need to set the jetty.port property to 8888. In Eclipse I use the following configuration:

Run integration tests from Eclipse

Run integration tests from Eclipse

7.2. Integration tests with SoapUI

Recently I’ve rediscovered SoapUI after using it heavily for testing SOAP based web services. With the recent versions (at the time of writing latest is 5.0.0) it offers pretty good functionality to test REST based web services, and coming versions should improve on this. So unless you develop your own framework/infrastructure to test REST services, why not give it a try to SoapUI. I did, I was satisfied with the results so far and I’ve decided to do a video tutorial, that you can now find on YouTube on our channel:

8. Versioning

There are three major possibilities

  1. URL:  “/v1/podcasts/{id}”
  2. Accept/Content-type header: application/json; version=1

Because I am a developer and not a RESTafarian yet I would do the URL option. All I would have to do on the implementation side for this example, would be to modify the @Path‘s value annotation on the PodcastResource class from to

Of course on a production application, you wouldn’t want every resource class preprefixed with the version number,  you’d want the version somehow treated through a filter in a AOP manner. Maybe something like this will come in a following post…

Here are some great resources from people that understand better the matter:

9. Compression

There may be cases when your REST api provides responses that are very long, and we all know how important transfer speed and bandwidth still are on mobile devices/networks. I think this is the first performance optimization point one needs to address, when developing REST apis that support mobile apps. Guess what? Because responses are text, we can compress them. And with today’s power of smartphones and tablets uncompressing them on the client side should not be a big deal…

On the server side, you can easily compress every response with Jersey’s EncodingFilter, which is a container filter that supports enconding-based content configuration. The filter examines what content encodings are supported by the container  and decides what encoding should be chosen based on the encodings listed in the Accept-Encoding request header and their associated quality values. To use particular content en/decoding, you need to register one or more content encoding providers  that provide specific encoding support; currently there are providers for GZIP and DEFLATE coding.

All I had to do in this case is adding the following line of code to my JaxRs application class:

10. Quick way to check if the REST API is alive

There might be cases when you want to quickly verify if your REST API, that is deployed either on dev, test or prod environments, is reachable altogether. A common way to do this is by building a generic resource that delivers for example the version of the deployed API. You can trigger a request to this resource manually or, even better, have a Jenkings/Hudson job, which runs a checkup job after deployment. In the post Quick way to check if the REST API is alive – GET details from Manifest file, I present how to implement such a service that reads default implementation and specification details from the application’s manifest file.

11. Security

11.1. Basic Authentication

Spring Security Framework’s powerful features were used to secure some REST resources (e.g. “/manifest”) with Basic Authentication. Read my following post How to secure Jersey REST services with Spring Security and Basic authentication to find out how.

12. Summary

Well, that’s it. I have to congratulate you, if you’ve come so far, but I hope you could learn something from this tutorial about REST, like designing a REST API, implementing a REST API in Java, testing a REST API and much more. If you did, I’d be very grateful if you helped it spread by leaving a comment or sharing it on Twitter, Google+ or Facebook. Thank you! Don’t forget also to check out Podcastpedia.org – you’ll find for sure interesting podcasts and episodes. We are grateful for your support.

If you liked this article, we would really appreciate a small contribution for our work! Donate now with Paypal.

Resources

Source Code

Web resources

  1. HTTP – Hypertext Transfer Protocol — HTTP/1.1 – RFC2616
  2. rfc5789 – PATCH Method for HTTP
  3. Jersey User Guide
  4. HTTP Status Code Definitions
  5. REST – http://en.wikipedia.org/wiki/Representational_State_Transfer
  6. CRUD – http://en.wikipedia.org/wiki/Create,_read,_update_and_delete
  7. Java API for RESTful Services (JAX-RS)
  8. Jersey – RESTful Web Services in Java
  9. HTTP PUT, PATCH or POST – Partial updates or full replacement?
  10. Transparent PATCH support in JAX-RS 2.0
  11. Maven Failsafe Plugin
  12. Maven Failsafe Plugin Usage
  13. SoapUI 5.0 released today!
  14. SoapUI – Using Script Assertions
  15. [Video] REST+JSON API Design – Best Practices for Developers
  16. [Video] RESTful API Design – Second Edition
  17. Law of Demeter

Codingpedia related resources

Podcastpedia image

Adrian Matei

Creator of Podcastpedia.org and Codingpedia.org, computer science engineer, husband, father, curious and passionate about science, computers, software, education, economics, social equity, philosophy - but these are just outside labels and not that important, deep inside we are all just consciousness, right?

About Adrian Matei

Creator of Podcastpedia.org and Codingpedia.org, computer science engineer, husband, father, curious and passionate about science, computers, software, education, economics, social equity, philosophy.

  • Pingback: RESTful Web Services Example in Java with Jersey, Spring and MyBatis | Codingpedia.org()

  • Pingback: How to add CORS support on the server side in Java with Jersey | Codingpedia.org()

  • Pingback: How to log in Spring with SLF4J and Logback | Codingpedia.org()

  • dude

    Would you have any best practice solution for Hateoas?

  • Atharv

    I was looking for a good REST examples from long time, this is awesome….

  • Nam

    This is amazing tutorial, very detailed, thank you

  • Leandro Fernandes

    hello Adrian!

    I’m trying to test this example but do not know where to start.

    I like to create the project in Eclipse using the folder I downloaded from github?

    • Hi Leandro,

      You can import it in Eclipse as a Maven project (File > Import > Select Existing Maven Projects). Once you did that, you can create a Maven Build configuration with the Goals set to clean install jetty:run -Djetty.port=8888 -DskipTests=true… as described on GitHub https://github.com/Codingpedia/demo-rest-jersey-spring … and run it from there.

      Adrian

    • Sanjeev Kumar Gupta

      download #postman client extension in any browser which is helpful to test rest api……

  • Alex Manusovich

    In /src/main/resources/logback.xml you have c:/tmp/minutes/rest-demo-minute.%d{yyyy-MM-dd_HH-mm}.log and c:/tmp/rest-demo.log

    • Hi Alex,
      the items you mentioned are in different file appenders. What is your point?

      Cheers
      Adrian

  • Jörgen Lundberg

    Hi Alex,
    I just wanted to thank you for taking the time and writing this post.
    /Jörgen

    • Hi Jörgen,

      I am glad you liked it. It’s Adrian, but you know Alex is also a nice name 🙂
      Adrian

      • Jörgen Lundberg

        Hi Adrian,
        How embarrassing…
        I guess I saw Alex in your reply to Alex below. 🙂
        /Jörgen

        • Hey Jörgen,
          It’s nothing to be embarrassed about, but in the Romanian tradition when you mix names you have to come with a lamb for Easter to the one you mixed the name for :P…

          Cheers,
          Adrian

  • Pingback: How to build and clear a reference data cache with singleton EJBs and MBeans | Codingpedia.org()

  • Pingback: Tutorial – REST API design and implementation in Java with Jersey and Spring | Dinesh Ram Kali.()

  • Albert Liu

    Hi Adrian,

    Thanks for posting this great tutorial!

    One question (not related to REST though), why we use @Transactional in PodcastResource? I think it is enough to use it in PodcastServiceDbAccessImpl.

    Albert

    • Hi Albert,

      You are right, this would have made better sense if there were more than one service classes accessing the database. But why not?
      Cheers,
      Adrian

  • André H Fauth

    Great post Adrian! It has helped me out a lot.

    I just don’t seem to get JSON response. Only in XML. Any idea?

    Thank you!

    • Hi André,
      Thank you.

      1) actually it the json format should have prio as defined on the resource’s method @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }). Anyway to force it to display the json content, add “Accept: application/json” to your request. In SOAP ui is just under the request:

      2) Please see the following links http://www.eclipse.org/jetty/documentation/current/enable-remote-debugging.html (down on the page you have links to debug with Eclipse and IntelliJ). I just start the server in Eclipse with the debug button instead of the run button….

      Hope this helps.

      Cheers,
      Adrian

      • Sudha Vuppalapati

        Hi can you tell me steps to add my own service and resources to same project
        I am getting error while adding resource not found

        • Hi Sudha,

          You mean to the SOAP ui project? Why would you want to do that?

          Adrian

          • It me

            Hi Adrian Matei,
            You can train step by step.
            Thanks you

  • André H Fauth

    Hi Adrian,

    I’m not a java expert. Do you have test unit examples with POST, PUT, DELETE and so on?

    Thank you!

  • Rui Brito

    Hi Adrian,
    Thank you for posting this tutorial, it was been a great help for me.

    I could use some help. I keep getting this error when I run the project ( I changed the name of the spring configuration file):

    “Error creating bean with name ‘entityManagerFactory’ defined in class path resource [spring/spring-config.xml]: Invocation of init method failed; nested exception is java.lang.IncompatibleClassChangeError: Implementing class”

    Could you help out with this matter? Thank you

    • Hi Rui,

      Can you post the full stacktrace?

      Thanks,
      Adrian

      • Rui Brito

        Hi Adrian,

        It is working now (so far). I tired many things, but I think that I made a mistake setting my MySQL connection. Haven’t test the POST, just GET and as @andrhfauth:disqus said, I could only get an XML response even with application.json even though I asked for JSON, but no worries there, I am sure it’s a mistake on my part and I will figure it out soon.

        What I think would be a great addition is some sort of authentication and/or verification of the requests to the API, if you are looking for a topic for the next tutorials.

        Thank you and keep it up,
        Rui

  • Miguel Angelo

    Amazing tutorial Adrian. It works perfectly!

    I am just having problems to deploy your solution. I have tested it with Tomcat, Jetty and Glassfish but not success.
    (it looks like I’m having some issues with hibernate and glassfish… it says “PodcastEntity is not mapped”. Maybe it is an issue with the database configuration)

    Which one do you prefer? Could give us an example with Jetty or Glassfish perhaps?

    Thank you!

    • Miguel Angelo

      I managed to Deploy it in Tomcat with your configurations. After checking Tomcat`s log I realized MySQL Connector jar was missing.
      Thanks for that great post!

      • Hi Miguel,
        Thanks and thanks for sharing with us your case.

        Cheers,
        Adrian

  • Dan

    Hi Adiran,
    I’m joining the Kudos for this post. It’s really the best step by step tutorial on the web that describe the use of these technologies.

    I have tried adding a little bit more functionality to the deployed web service.
    On top of exposing the Rest API I would also like to have the web server host some html files.
    I have tried looking on how to do it, but since I’m new to all of the technologies (Maven, Jetty, Spring, etc..) I couldn’t find any solution that worked.

    Could you please assist?

    • Hi Dan,

      Thanks for the kind words.

      You basically need another servlet serving those files. Do you want to do with Spring?
      I will do a post next week covering Jersey integration with Spring MVC, where on the same server/war file I will be serving both a REST api and a classical web application.
      So stay tuned on Codingpedia.org as it will be published soon.

      Cheers,
      Adrian

      • Dan

        Adding another servlet sounds like a good idea – but I was not sure how to that. Where would I define it? and where should I put the html files?
        Do you have any references or snippets I could use?

        Another option I was trying is to deploy another webapp only for the html files.

        Thanks,
        Dan.

        • Dan

          Got it! The problem was that the servlet is defined with /* which hogs all requests to the web service.

          All other servlets will not get the chance to respond.

          Once I changed it to /api/* I was able to place html files in the webapp folder and the jetty just returns them

          Thanks for everything.

  • Pingback: How to integrate Jersey in a Spring MVC application | Codingpedia.org()

  • Hi Adrian,

    Amazing work!

    For those interested in Spring Boot: with recently released Spring Boot 1.2 Jersey configuration comes out of the box. You only need add one dependency to the Spring Boot project and thanks to auto-configuration you will get up and running within seconds. Have a look at Spring Boot documentation: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-jersey

    I also blogged about how to get started with Jersey and Spring Boot (and Spring Data, Spring Integration Test and Spring Security): http://blog.codeleak.pl/2015/01/getting-started-with-jersey-and-spring.html

    • Hi Rafał,
      Thanks for the update and sharing – great work.

      Cheers,
      Adrian

  • Pingback: How to secure Jersey REST services with Spring Security and Basic authentication | Codingpedia.org()

  • Pingback: rest-jersey-tutorials | mauroprogram's Blog()

  • Simone

    Hello Adrian, I’m trying to run your application in JBoss EAP 6.2. After making the changes I thought were necessary to adapt it to JBoss, when I start the server encounter this problem that I can not solve:

    JBAS014775: New missing/unsatisfied dependencies:
    service jboss.naming.context.java.jboss.resources.jdbc.restDemoDB (missing) dependents: [service jboss.naming.context.java.module.demo-rest-jersey-spring.demo-rest-jersey-spring.env.jdbc.restDemoDB]
    service jboss.naming.context.java.jboss.resources.jdbc.restDemoLegacyDB (missing) dependents: [service jboss.naming.context.java.module.demo-rest-jersey-spring.demo-rest-jersey-spring.env.jdbc.restDemoLegacyDB]

    could you help me figure out how to fix it please?

  • Banks

    Hi Adrian,

    How to the config with glassfish?

  • John Allred

    Hi Adrian,

    Thanks for this wonderful tutorial. I was able to get the rest server running !! with the command below i was able get it running via jetty

    mvn clean install jetty:run -Djetty.port=8888 -DskipTests=true

    1. i have installed tomcat, so what is command to run the rest using the tomcat?
    2. how can i open this project in eclipse?

    Thanks again.

  • John Allred

    Another question.

    i created the WAR file using mvn install command. deployed the WAR file onto tomcat (bitnami) and clicked on START but got this error

    FAIL – Application at context path /demo-rest-jersey-spring could not be started

  • Praveen Kumar

    Hi Adrian,
    Very nice step by step article to demonstrate RESTFull Methods and how to create a RESTFull Api.
    I was wondering if you had a chance to look in to Apache components ( Camel, FOP etc.).
    I have a query, any advise please “What would be the right structure for a REST Api to create a PDF and POST the data to a service”?

    Thanks
    Prav

  • GARYM

    Builds fin In Intellij 16. Deploying on Weblogic 12.1.3.0 and I see this mess:
    com.sun.jersey.spi.inject.Errors$ErrorMessagesException:com.sun.jersey.spi.inject.Errors.ErrorMessagesException:null