Skip to content

sirajul116/sequence-generator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sequence Generator

A Spring Boot 3.2 / Java 17 service that generates monotonically increasing sequence values backed by PostgreSQL.

It is designed to reserve IDs in batches from the database, cache them in memory, and serve them safely under concurrent load.

Highlights

  • PostgreSQL-backed named sequences such as ORDER, USER, and INVOICE
  • Batch reservation to reduce database round-trips
  • In-memory range cache with per-sequence locking
  • REST API for raw and formatted sequence values
  • Structured error responses via a global exception handler
  • Database bootstrap via schema.sql

Tech stack

  • Java 17
  • Spring Boot 3.2.3
  • Spring Web
  • Spring Data JPA
  • PostgreSQL
  • Validation
  • springdoc-openapi (dependency included)

Project structure

src/main/java/com/example/seqgen/
├── SequenceGeneratorApplication.java   # Application entry point
├── config/
│   └── SequenceProperties.java         # sequence.* configuration
├── controller/
│   ├── GlobalExceptionHandler.java     # JSON error handling
│   └── SequenceController.java         # REST endpoints
├── entity/
│   └── Sequence.java                   # JPA entity for sequences table
├── repository/
│   └── SequenceRepository.java         # Native SQL data access
└── service/
    ├── Range.java                      # In-memory reserved number window
    └── SequenceGeneratorService.java   # Core sequence generation logic

src/main/resources/
├── application.yml                     # Application and database settings
└── schema.sql                          # Table creation and seed data

How it works

  1. The service receives a request for a sequence type, such as ORDER.
  2. It first tries to serve the next value from an in-memory Range.
  3. If the range is missing or exhausted, it acquires a per-type lock.
  4. It then reserves the next batch from PostgreSQL using a single atomic UPDATE ... RETURNING statement.
  5. The reserved range is cached in memory and handed out one value at a time.

This design means:

  • fast reads when a cached batch is available
  • no overlapping ranges across concurrent application instances
  • fewer database calls than reserving one value at a time

Database initialization

src/main/resources/schema.sql is executed on startup because application.yml sets:

spring:
  sql:
    init:
      mode: always

That means the script runs every time the application starts, not only on the first run.

The script:

  • creates the sequences table if it does not exist
  • seeds the default sequence names:
    • ORDER
    • USER
    • INVOICE

The SQL is idempotent, so re-running it is safe:

  • CREATE TABLE IF NOT EXISTS
  • INSERT ... ON CONFLICT DO NOTHING

Configuration

The default configuration is in src/main/resources/application.yml.

Database

spring:
  datasource:
    url: jdbc:postgresql://localhost:5433/seqdb
    username: postgres
    password: postgres

Sequence settings

sequence:
  batch-size: 50
  supported-types:
    - ORDER
    - USER
    - INVOICE

Notes:

  • batch-size controls how many values are reserved per database call.
  • supported-types is validated as non-empty and documents the intended default sequence names; the current startup script seeds the defaults directly.
  • The service currently accepts new types on first use by upserting them into the table.

REST API

Base path: /api/v1/sequences

Get next raw value

GET /api/v1/sequences/{type}/next

Example:

GET /api/v1/sequences/ORDER/next

Response:

{
  "type": "ORDER",
  "value": 42
}

Get next formatted value

GET /api/v1/sequences/{type}/next/formatted

Example:

GET /api/v1/sequences/ORDER/next/formatted

Response:

{
  "type": "ORDER",
  "value": "ORDER-000042"
}

API documentation (Swagger/OpenAPI)

The project includes springdoc-openapi-starter-webmvc-ui, so Swagger UI and OpenAPI docs are available when the app is running.

  • Swagger UI: http://localhost:8080/swagger-ui/index.html
  • Alternate Swagger UI path: http://localhost:8080/swagger-ui.html
  • OpenAPI JSON: http://localhost:8080/v3/api-docs
  • OpenAPI YAML: http://localhost:8080/v3/api-docs.yaml

Use Swagger UI to test these endpoints interactively:

  • GET /api/v1/sequences/{type}/next
  • GET /api/v1/sequences/{type}/next/formatted

Error handling

The app returns structured JSON for common failures:

  • 400 Bad Request for invalid input such as a blank sequence type
  • 500 Internal Server Error for unexpected or database-related failures

Example error body:

{
  "error": "Sequence type must not be blank",
  "timestamp": "2026-04-18T12:34:56.789Z"
}

Implementation notes

  • SequenceGeneratorService normalizes types to uppercase.
  • Range is an in-memory window backed by AtomicLong.
  • Each sequence type has its own ReentrantLock, so different types do not block each other during range refresh.
  • The repository uses native PostgreSQL SQL for atomic range reservation.
  • spring.sql.init.mode=always means schema initialization happens on every startup.
  • There are currently no checked-in automated tests under src/test/java.

Requirements

  • Java 17
  • Maven 3.9+ recommended
  • PostgreSQL running on localhost:5433 with a database named seqdb

Docker (database only)

This repository already includes a docker-compose.yml file for PostgreSQL. It runs the database in Docker while the Spring Boot application runs on your machine.

Start the database

docker compose up -d db

This starts a PostgreSQL 16 container with:

  • database: seqdb
  • user: postgres
  • password: postgres
  • host port: 5433

The app is already configured to connect to:

jdbc:postgresql://localhost:5433/seqdb

So no code changes are needed if you use the default Compose setup.

Stop the database

docker compose down

To remove the persisted database data as well:

docker compose down -v

Notes

  • The seqdb-data volume keeps database data across restarts.
  • There is currently no Dockerfile for the Spring Boot application itself.
  • If you later containerize the app too, the datasource host should change from localhost to the Compose service name db.

Run locally

  1. Create the PostgreSQL database and user if needed.
  2. Or start PostgreSQL with Docker using the commands above.
  3. Make sure the database is reachable at the configured host and port.
  4. Start the application:
mvn spring-boot:run

Or build and run the jar:

mvn clean package
java -jar target/sequence-generator-1.0.0.jar

Example curl commands

curl http://localhost:8080/api/v1/sequences/ORDER/next
curl http://localhost:8080/api/v1/sequences/ORDER/next/formatted

License

No license file is currently included in the repository.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages