Language: Java
Web
Jersey was developed by Oracle (originally as part of GlassFish) to provide a standard, annotation-driven framework for creating RESTful web services on the Java platform. It supports both client-side and server-side APIs, integrates with CDI (Contexts and Dependency Injection), and provides filters, exception handling, and advanced features such as asynchronous processing. Over the years, Jersey has become a widely used framework in enterprise and microservice applications due to its adherence to standards and ease of integration.
Jersey is the reference implementation of JAX-RS (Java API for RESTful Web Services) for building RESTful web services in Java. It simplifies creating web services with annotations, dependency injection, and automatic JSON/XML support.
Add the following dependencies in your pom.xml:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>3.2.0</version>
</dependency>Add the following dependencies in build.gradle:
implementation 'org.glassfish.jersey.core:jersey-server:3.2.0'
implementation 'org.glassfish.jersey.containers:jersey-container-servlet:3.2.0'
implementation 'org.glassfish.jersey.media:jersey-media-json-binding:3.2.0'Jersey allows you to define REST endpoints using annotations such as @Path, @GET, @POST, @PUT, @DELETE, and @Produces/@Consumes for content negotiation. It supports JSON/XML serialization, request/response filtering, exception mapping, dependency injection via CDI, asynchronous endpoints, and client-side APIs for consuming other REST services.
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class HelloResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello Jersey!";
}
}Defines a basic GET endpoint that returns a plain text response at the path `/hello`.
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/users")
public class UserResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public User createUser(User user) {
// save user to database or service
return user;
}
}Defines a POST endpoint that accepts a JSON object, processes it, and returns a JSON response.
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/service")
public class ServiceResource {
@Inject
MyService myService;
@GET
public String getMessage() {
return myService.getMessage();
}
}Demonstrates injecting a service bean into a Jersey resource using CDI.
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import jakarta.ws.rs.core.Response;
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(exception.getMessage())
.build();
}
}Custom exception mapper that catches all exceptions thrown by endpoints and returns a structured HTTP response.
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.ext.Provider;
@Provider
public class LoggingFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) {
System.out.println("Incoming request: " + requestContext.getUriInfo().getRequestUri());
}
}Implements a request filter to log all incoming requests.
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.container.AsyncResponse;
import jakarta.ws.rs.container.Suspended;
import java.util.concurrent.CompletableFuture;
@Path("/async")
public class AsyncResource {
@GET
public void asyncHello(@Suspended AsyncResponse response) {
CompletableFuture.supplyAsync(() -> "Hello Async Jersey!")
.thenAccept(response::resume);
}
}Demonstrates asynchronous processing with @Suspended AsyncResponse and CompletableFuture.
Use standard JAX-RS annotations for REST endpoints to maintain portability.
Leverage CDI for dependency injection and modular design.
Use ExceptionMappers to handle errors consistently.
Use Filters and Interceptors for cross-cutting concerns like logging, authentication, and metrics.
Separate resource classes, services, and domain models for maintainable architecture.