DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Key Takeaways From Integrating a RAG Application With LangSmith
  • Improving Java Application Reliability with Dynatrace AI Engine
  • Jakarta NoSQL in Jakarta EE 12 M2: A Maturing Story of Polyglot Persistence
  • Enabling Single-Sign-On in SaaS Application

Trending

  • OpenAPI From Code With Spring and Java: A Recipe for Your CI
  • Testing AI-Infused Apps: A Dual-Layer Framework for AI Quality Assurance
  • Stateless JWT Auth Microservice Architecture With Spring Boot 3 and Redis Sentinel
  • Contract-First Integration: Building Scalable Systems With Flyway, OpenAPI, and Kafka
  1. DZone
  2. Data Engineering
  3. Data
  4. Handling Pagination With JAX-RS and NoSQL in Your Jakarta EE/MicroProfile Application

Handling Pagination With JAX-RS and NoSQL in Your Jakarta EE/MicroProfile Application

Want to learn more about handling pagination with JAX-RS? Look no further than Jakarta EE and MicroProfile.

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Aug. 07, 19 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
15.8K Views

Join the DZone community and get the full member experience.

Join For Free

As we've discussed in the previous post, "pagination is the process of separating the contents into discrete pages." It is useful in RESTful applications because we can avoid the waste of a database, server, and networking among the client and the server. This post will create a simple pagination application with JAX-RS where you can apply both Jakarta EE and MicroProfile.

This post will use MongoDB with a Car entity to demonstrate how pagination works with the Jakarta NoSQL API.

The MongoDB database must be running while the server is up, so you can either download and install it manually or use a Docker image and then run the command:

docker run -d --name mongodb-instance -p 27017:27017 mongo


The project is a Jakarta EE and Jakarta NoSQL running through Maven with Payara Micro; thus, all configurations and dependencies are the pom.xml file. The Jakarta NoSQL project has been approved, but it isn't a final version; therefore, the sample uses a SNAPSHOT version.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.soujava</groupId>
    <artifactId>cars</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>cars-pagination-demo</name>

    <url>https://soujava.org.br/</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.ee.version>8.0</java.ee.version>
        <java.se.version>1.8</java.se.version>
        <payara.version>1.0.5</payara.version>
        <version.payara.micro>5.192</version.payara.micro>
        <jnosql.version>0.1.0-SNAPSHOT</jnosql.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>${java.ee.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jnosql.artemis</groupId>
            <artifactId>artemis-document</artifactId>
            <version>${jnosql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jnosql.diana</groupId>
            <artifactId>mongodb-driver</artifactId>
            <version>${jnosql.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>cars</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.se.version}</source>
                    <target>${java.se.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.0.0</version>
            </plugin>
            <plugin>
                <groupId>fish.payara.maven.plugins</groupId>
                <artifactId>payara-micro-maven-plugin</artifactId>
                <version>${payara.version}</version>
                <configuration>
                    <payaraVersion>${version.payara.micro}</payaraVersion>
                    <autoDeployEmptyContextRoot>true</autoDeployEmptyContextRoot>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>snapshots-repo</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>


The Car entity has five attributes: id, provider, model, year, and color.

import jakarta.nosql.mapping.Column;
import jakarta.nosql.mapping.Entity;
import jakarta.nosql.mapping.Id;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;

@Entity
public class Car {
    @Id
    private Long id;
    @Column
    @NotBlank
    private String provider;
    @Column
    @NotBlank
    private String model;
    @Column
    @Positive
    private Integer year;
    @Column
    @NotBlank
    private String color;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getProvider() {
        return provider;
    }

    public void setProvider(String provider) {
        this.provider = provider;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public Integer getYear() {
        return year;
    }

    public void setYear(Integer year) {
        this.year = year;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", provider='" + provider + '\'' +
                ", model='" + model + '\'' +
                ", year=" + year +
                ", color='" + color + '\'' +
                '}';
    }
}


Once the entity is ready, the next step is to create the CarRepository using findAll with pagination.

import jakarta.nosql.mapping.Pagination;
import jakarta.nosql.mapping.Repository;

import java.util.List;

public interface CarRepository extends Repository<Car, Long> {

    List<Car> findAll(Pagination pagination);
}


At the Jakarta NoSQL project, we have several ways to configure the Mongo Client such as XML, JSON, YAML, properties, and programmatically. This project uses the JSON configuration.

[
  {
    "description":"MongoDB configuration",
    "name":"mongodb",
    "provider":"org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration",
    "settings":{
      "jakarta.nosql.host":"localhost"
    }
  }
]


At JAX-RS, there isn't an interface that represents pagination in a resource. Therefore, we can create a straightforward example to demonstrate the concept. The class has two attributes, one to show the page and the last one to define the size of elements of each page both from QueryParam and with validation, allowing positive value on both attributes.

import jakarta.nosql.mapping.Pagination;

import javax.validation.constraints.Positive;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.QueryParam;

public class PageRequest {

    @QueryParam("page")
    @DefaultValue("1")
    @Positive
    private long page;

    @QueryParam("size")
    @DefaultValue("3")
    @Positive
    private long size;

    public long getPage() {
        return page;
    }

    public void setPage(long page) {
        this.page = page;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public Pagination toPagination() {
        return Pagination.page(page).size(size);
    }

    @Override
    public String toString() {
        return "PageRequest{" +
                "page=" + page +
                ", size=" + size +
                '}';
    }
}


The last step in the code is the JAX-RS integration with the resource class.

@ApplicationPath("/resource")
public class ApplicationConfiguration extends Application {
}

import jakarta.nosql.mapping.ConfigurationUnit;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.function.Supplier;

@ApplicationScoped
@Path("cars")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class CarResource {

    private static final Supplier<WebApplicationException> NOT_FOUND =
            () -> new WebApplicationException(Response.Status.NOT_FOUND);

    @Inject
    @ConfigurationUnit(database = "car")
    private CarRepository repository;

    @GET
    public List<Car> findAll(@BeanParam @Valid PageRequest page) {
        return repository.findAll(page.toPagination());
    }

    @GET
    @Path("/{id}")
    public Car findById(@PathParam("id") Long id) {
        return repository.findById(id).orElseThrow(NOT_FOUND);
    }


    @POST
    public void insert(@Valid Car car) {
        repository.save(car);
    }

    @PUT
    @Path("/{id}")
    public void update(@PathParam("id") Long id, @Valid Car car) {
        repository.save(car);
    }

    @Path("/{id}")
    @DELETE
    public void delete(@PathParam("id") Long id) {
        repository.deleteById(id);
    }
}


The ConfigurationUnit annotation allows injecting the repository from the configuration instead of programmatically. The project is ready to launch; with Payara Micro, we can do it easily with two steps: one to compile and the second one to run the uber jar.

mvn -DskipTests clean package payara-micro:bundle
java -jar target/cars-microbundle.jar


Once the project is running, it is time to create a script to inject entities from an HTTP POST request.

curl -H "Content-Type: application/json" -X POST -d '{"id":1,"provider":"Dodge","model":"Caravan","year":2006,"color":"Teal"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":2,"provider":"Lamborghini","model":"Aventador","year":2012,"color":"Blue"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":3,"provider":"Mitsubishi","model":"Pajero","year":1997,"color":"Green"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":4,"provider":"Mazda","model":"Miata MX-5","year":2005,"color":"Mauv"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":5,"provider":"Dodge","model":"Aries","year":1981,"color":"Blue"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":6,"provider":"Ford","model":"Windstar","year":1995,"color":"Yellow"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":7,"provider":"Subaru","model":"Impreza","year":1999,"color":"Purple"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":8,"provider":"Plymouth","model":"Acclaim","year":1995,"color":"Khaki"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":9,"provider":"Audi","model":"200","year":1990,"color":"Puce"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":10,"provider":"Kia","model":"Spectra","year":2009,"color":"Crimson"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":11,"provider":"Volkswagen","model":"Golf","year":2001,"color":"Crimson"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":12,"provider":"Chevrolet","model":"Silverado 1500","year":2008,"color":"Indigo"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":13,"provider":"Studebaker","model":"Avanti","year":1961,"color":"Turquoise"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":14,"provider":"Audi","model":"100","year":1994,"color":"Purple"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":15,"provider":"Ford","model":"Taurus","year":2003,"color":"Maroon"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":16,"provider":"GMC","model":"Acadia","year":2010,"color":"Indigo"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":17,"provider":"Toyota","model":"Camry Hybrid","year":2011,"color":"Violet"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":18,"provider":"Buick","model":"Roadmaster","year":1996,"color":"Purple"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":19,"provider":"Mercury","model":"Monterey","year":2006,"color":"Mauv"}' http://localhost:8080/resource/cars
curl -H "Content-Type: application/json" -X POST -d '{"id":20,"provider":"GMC","model":"Sierra","year":2010,"color":"Violet"}' http://localhost:8080/resource/cars


We can enjoy the pagination using a few request queries:

http://localhost:8080/resource/cars
[
   {
      "color":"Teal",
      "id":1,
      "model":"Caravan",
      "provider":"Dodge",
      "year":2006
   },
   {
      "color":"Blue",
      "id":2,
      "model":"Aventador",
      "provider":"Lamborghini",
      "year":2012
   },
   {
      "color":"Green",
      "id":3,
      "model":"Pajero",
      "provider":"Mitsubishi",
      "year":1997
   }
]

http://localhost:8080/resource/cars?page=2

[
   {
      "color":"Mauv",
      "id":4,
      "model":"Miata MX-5",
      "provider":"Mazda",
      "year":2005
   },
   {
      "color":"Blue",
      "id":5,
      "model":"Aries",
      "provider":"Dodge",
      "year":1981
   },
   {
      "color":"Yellow",
      "id":6,
      "model":"Windstar",
      "provider":"Ford",
      "year":1995
   }
]

http://localhost:8080/resource/cars?page=4&size=5

[
   {
      "color":"Indigo",
      "id":16,
      "model":"Acadia",
      "provider":"GMC",
      "year":2010
   },
   {
      "color":"Violet",
      "id":17,
      "model":"Camry Hybrid",
      "provider":"Toyota",
      "year":2011
   },
   {
      "color":"Purple",
      "id":18,
      "model":"Roadmaster",
      "provider":"Buick",
      "year":1996
   },
   {
      "color":"Mauv",
      "id":19,
      "model":"Monterey",
      "provider":"Mercury",
      "year":2006
   },
   {
      "color":"Violet",
      "id":20,
      "model":"Sierra",
      "provider":"GMC",
      "year":2010
   }
]


In this post, we created a simple JAX-RS that can use both Eclipse projects, Jakarta EE and MicroProfile. The code is ready, so feel free to open a Pull Request to make it even more significant. In our next post, we'll create a pagination project with Eclipse Krazo and HTML 5. Stay tuned!

NoSQL application

Opinions expressed by DZone contributors are their own.

Related

  • Key Takeaways From Integrating a RAG Application With LangSmith
  • Improving Java Application Reliability with Dynatrace AI Engine
  • Jakarta NoSQL in Jakarta EE 12 M2: A Maturing Story of Polyglot Persistence
  • Enabling Single-Sign-On in SaaS Application

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook