by Rafał Borowiec

Menu

Monday, January 5, 2015

Along many new features, Spring Boot 1.2 brings Jersey support. This is great step to attract those developers who like the standard approach as they can now build RESTful APIs using JAX-RS specification and easily deploy it to Tomcat or any other Spring’s Boot supported container. Jersey with Spring platform can play an important role in the development of mico services. In this article I will demonstrate how one can quickly build an application using Spring Boot (including: Spring Data, Spring Test, Spring Security) and Jersey.

Bootstrap a new project

The application is a regular Spring Boot application and it uses Gradle and its latest 2.2 release. Gradle is less verbose than Maven and it is especially great for Spring Boot applications. Gradle can be downloaded from Gradle website: http://www.gradle.org/downloads.

Jersey 2.x has native Spring support (jersey-spring3) and Spring Boot provides auto-configuration support for it with spring-boot-starter-jersey starter. For more details have a look atJerseyAutoConfiguration class.

Depending on the spring.jersey.type property value either Jersey Servlet or Filter is registered as a Spring Bean:

The JSON media type support comes with jersey-media-json-jackson dependency that registers Jackson JSON providers to be used by Jersey.

Spring Data JPA Integration

Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. For those who are not familiar with the project please visit: http://projects.spring.io/spring-data-jpa/

Customer and CustomerRepository

Domain model for this sample project is just a Customer with some basic fields:

With the domain model in place some test data can be handy. The easiest way is to provide a data.sql file with the SQL script to be executed on the application start-up. The file is placed in src/main/resources and it will be automatically picked up by Spring. The script contains several SQL inserts to fill in the customer table. E.g:

To verify the above code I created Spring integration test. In first test I will call for all the records, and based on test data previously prepared I expect to have total 3 customers in 1 page of size 20:

In the second test I will call for page 0 of size 1 and sorting by firstname and sorting direction descending. I expect total elements did not change (3), total pages returned are 3 and content size of the page returned is 1:

Please note that for ease of testing the pagination with RestTemplate I created some helper classes: Page, Sort and PageAssertion. You will find them in the source code of the application in Github.

Add New Customer

In this short snippet I used some of the Jersey features like injecting a @Context. In case of creating new entity, we usually want to return a link to the resource in the header. In the below example, I inject UriBuilder into the endpoint class and use it to build a location URI of newly created customer:

Security

Adding Spring Security to the application can be done quickly by adding new dependency to the project:

compile("org.springframework.boot:spring-boot-starter-security")

With Spring Security in classpath application will be secured with basic authentication on all HTTP endpoints. Default username and password can be changed with two following application settings (src/main/resources/application.properties):

security.user.name=demo
security.user.password=123

After running the application with Spring Security application we need to provide a valid authentication parameters to each request. With curl we can use --user switch:

$ curl -i --user demo:123 -X GET http://localhost:8080/customer/1

With the addition of Spring Security our previously created tests will fail, so we need to provide username and password parameters to RestTemplate:

With the above code I expected to have both health and spring-health endpoints available in the root context but apparently it did not work. I tried several configuration options, including setting spring.jersey.filter.order but with no success.

The only solution I found was to either change Jersey @ApplicationPath or to change Spring MVC server.servlet-path property: