We will start with project setup and then create a root resource/ controller class, create jersey configuration class, register exception mappers and finally run the application and test endpoints with Postman.
Previous posts
We will add spring-boot-starter-parent
as parent of our maven based project. The added benefit of this is version management for spring dependencies.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.0.RELEASE</version>
</parent>
Next, we will add spring-boot-starter-jersey
dependency to the pom.xml
.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
Next, we will add spring-boot-starter-undertow
dependency to the pom.xml
.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
These are all minimum necessary spring-boot-starters
we require to create Restful webservices with Jersey.
We will create a root resource first.
What are Root resource classes?
Root resource classes are POJOs that are either annotated with
@Path
or have at least one method annotated with@Path
or a request method designator, such as@GET
,@PUT
,@POST
, or@DELETE
.
@Component
@Path("/books")
public class BookController {
private BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
@GET
@Produces("application/json")
public Collection getAllBooks() {
return bookService.getAllBooks();
}
@GET
@Produces("application/json")
@Path("/{oid}")
public Book getBook(@PathParam("oid") String oid) {
return bookService.getBook(oid);
}
@POST
@Produces("application/json")
@Consumes("application/json")
public Response addBook(Book book) {
bookService.addBook(book);
return Response.created(URI.create("/" + book.getOid())).build();
}
@PUT
@Consumes("application/json")
@Path("/{oid}")
public Response updateBook(@PathParam("oid") String oid, Book book) {
bookService.updateBook(oid, book);
return Response.noContent().build();
}
@DELETE
@Path("/{oid}")
public Response deleteBook(@PathParam("oid") String oid) {
bookService.deleteBook(oid);
return Response.ok().build();
}
}
We have created a BookController
class and used JAX-RS annotations.
@Path
is used to identify the URI path (relative) that a resource class or class method will serve requests for.@PathParam
is used to bind the value of a URI template parameter or a path segment containing the template parameter to a resource method parameter, resource class field, or resource class bean property. The value is URL decoded unless this is disabled using the @Encoded
annotation.@GET
indicates that annotated method handles HTTP GET requests.@POST
indicates that annotated method handles HTTP POST requests.@PUT
indicates that annotated method handles HTTP PUT requests.@DELETE
indicates that annotated method handles HTTP DELETE requests.@Produces
defines a media-type that the resource method can produce.@Consumes
defines a media-type that the resource method can accept.You might have noticed that we have annotated BookController
with @Component
which is Spring's annotation and register it as bean. We have done so to benefit Spring's DI for injecting BookService
service class.
@Configuration
@ApplicationPath("rest")
public class JerseyConfiguration extends ResourceConfig {
public JerseyConfiguration() {
}
@PostConstruct
public void setUp() {
register(BookController.class);
register(GenericExceptionMapper.class);
}
}
We created a JerseyConfiguration
class which extends the ResourceConfig
from package org.glassfish.jersey.server
which configures the web application. In the setUp()
, we registered BookController
and GenericExceptionMapper
.
@ApplicationPath
identifies the application path that serves as the base URI for all the resources.
Could there be a case that some exceptions occurs in the resource methods (Runtime/ Checked). You can write your own custom exception mappers to map Java exceptions to javax.ws.rs.core.Response
.
@Provider
public class GenericExceptionMapper implements ExceptionMapper {
@Override
public Response toResponse(Throwable exception) {
return Response.serverError().entity(exception.getMessage()).build();
}
}
We have created a generic exception handler by catching Throwable
. Ideally, you should write finer-grained exception mapper.
What is @Provider annotation?
It marks an implementation of an extension interface that should be discoverable by JAX-RS runtime during a provider scanning phase.
We have also created service BookService
, model Book
also. You can see the full code on Github.
You can use maven to directly run it with mvn spring-boot:run
command or can create a jar and run it.
I have used PostMan extension available in chrome brower to test rest services. You can use any package/ API/ software to test it.
This is how we create Restful web-services with Jersey in conjuction with Spring Boot. I hope you find this post informative and helpful to create your first but not last Restful web-service.