Search

Suggested keywords:
  • Java
  • Docker
  • Git
  • React
  • NextJs
  • Spring boot
  • Laravel

Build REST API using Jersey in Java

  • Share this:

post-title

Jersey, a reference implementation of JAX-RS (Java API for RESTful Web Services), empowers developers to create robust RESTful APIs in Java. With its simplicity and extensive features, it is one of the most popular choices for building REST-compliant web services. In this article, we'll dive into creating a RESTful API using Jersey, covering the creation of entity classes, service classes, and resource classes.

Setting Up the Project

Before delving into code, ensure you have Jersey included in your project dependencies. If you want to manage dependencies with Jersey libraries, you can download them or use a build tool like Maven like below

<dependency>
    <groupId>jakarta.ws.rs</groupId>
    <artifactId>jakarta.ws.rs-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>3.1.7</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>3.1.7</version>
</dependency>

 

Creating Entity Classes

Entity classes represent the data model of your application. For our example, let's create a simple entity class representing a book:

public class Book {
    private int id;
    private String title;
    private String author;
}

 

Implementing Service Classes

Service classes handle the business logic of your application. They interact with databases, perform CRUD operations, and manipulate data. In our case, let's create a service class for managing books.

import java.util.List;
import java.util.Optional;

public class BookService {
    private BookRepository bookRepository = new BookRepository();

    public List<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    public Optional<Book> getBookById(int id) {
        return bookRepository.findById(id);
    }

    public Book addBook(Book book) {
        return bookRepository.save(book);
    }

    public Optional<Book> updateBook(int id, Book updatedBook) {
        return bookRepository.findById(id).map(existingBook -> {
            existingBook.setTitle(updatedBook.getTitle());
            existingBook.setAuthor(updatedBook.getAuthor());
            return bookRepository.save(existingBook);
        });
    }

    public boolean deleteBook(int id) {
        return bookRepository.deleteById(id);
    }
}

 

Create Resource Class using Jersey Annotations

Resource classes expose your API endpoints and define the HTTP methods they respond to. Let's create a resource class for managing book-related operations.

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Optional;

@Path("/books")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class BookResource {
    private BookService bookService = new BookService();

    @GET
    public List<Book> getAllBooks() {
        return bookService.getAllBooks();
    }

    @GET
    @Path("/{id}")
    public Response getBookById(@PathParam("id") int id) {
        Optional<Book> book = bookService.getBookById(id);
        if (book.isPresent()) {
            return Response.ok(book.get()).build();
        } else {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }

    @POST
    public Response addBook(Book book) {
        Book createdBook = bookService.addBook(book);
        return Response.status(Response.Status.CREATED).entity(createdBook).build();
    }

    @PUT
    @Path("/{id}")
    public Response updateBook(@PathParam("id") int id, Book book) {
        Optional<Book> updatedBook = bookService.updateBook(id, book);
        if (updatedBook.isPresent()) {
            return Response.ok(updatedBook.get()).build();
        } else {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }

    @DELETE
    @Path("/{id}")
    public Response deleteBook(@PathParam("id") int id) {
        boolean deleted = bookService.deleteBook(id);
        if (deleted) {
            return Response.noContent().build();
        } else {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }
}

 

BookRepository Class

This class will handle the data access logic. For simplicity, I'll continue using an in-memory list to store the books, but in a real application, this would interact with a database.

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class BookRepository {
    private static List<Book> books = new ArrayList<>();
    private static int currentId = 1;

    public List<Book> findAll() {
        return new ArrayList<>(books);
    }

    public Optional<Book> findById(int id) {
        return books.stream().filter(book -> book.getId() == id).findFirst();
    }

    public Book save(Book book) {
        if (book.getId() == 0) {
            book.setId(currentId++);
            books.add(book);
        } else {
            books.set(books.indexOf(findById(book.getId()).orElse(null)), book);
        }
        return book;
    }

    public boolean deleteById(int id) {
        return books.removeIf(book -> book.getId() == id);
    }
}

 

Configuring Jersey

Now, let's configure Jersey for our web application. There are two common ways to configure Jersey:

 

Configuration via web.xml

Create a web.xml file in the WEB-INF directory of your web application. Configure Jersey servlet and mapping within the web.xml file

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>JerseyServlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.example.MyApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>JerseyServlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

</web-app>

 

Configuration via Application class

Create a class that extends javax.ws.rs.core.Application.

package com.example;

import org.glassfish.jersey.server.ResourceConfig;

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        packages("com.example.resources");
    }
}

In this example, MyApplication class extends ResourceConfig, where we register our resource classes.

 

Running the Application and Testing Endpoints

To run the application, deploy it to a servlet container such as Apache Tomcat. Once deployed, you can test the RESTful API endpoints using tools like Postman or simply by accessing them via a web browser.

Output

If books are added to the BookService, accessing the same endpoint will return

[
  {
    "id": 1,
    "title": "Book Title",
    "author": "Author Name"
  }
]

The actual JSON output will depend on the specific books that have been added to the service.

Conclusion

In this article, we've demonstrated how to build a RESTful API with Jersey in Java. We covered creating entity classes to represent data, service classes to handle business logic, and resource classes to define API endpoints. We also discussed configuring Jersey either via web.xml or programmatically using a subclass of javax.ws.rs.core.Application. Experiment with Jersey's features and explore advanced topics to further enhance your RESTful API development skills.

Muthu Annamalai

About author
Technical Writer | Pre-Final Year Student | Code & Community | Developer who works everyday to improve himself.