Skip to content

Instantly share code, notes, and snippets.

@antonarhipov
Created April 7, 2025 07:57
Show Gist options
  • Save antonarhipov/7b81ff62055ad4dabba6ccda1279453e to your computer and use it in GitHub Desktop.
Save antonarhipov/7b81ff62055ad4dabba6ccda1279453e to your computer and use it in GitHub Desktop.
Spring Boot Junie guidelines

Spring Boot Style Guide for Bookstore Application

This document outlines the coding standards, architectural patterns, and best practices for the Bookstore application.

Technology Stack

Frontend

  • React 18 for building user interfaces
  • Tailwind CSS for utility-first styling
  • Vite for frontend tooling and development environment

Backend

  • Spring Boot as the application framework
  • RESTful APIs for data exchange and communication between client and server
  • Spring Data JDBC for persistence (not JPA/Hibernate)
  • MySQL as the database system

Testing

  • TestContainers for integration testing with real database instances
  • JUnit 5 for test framework
  • DO NOT use mocks - prefer real dependencies or test doubles

Excluded Technologies

  • DO NOT use Lombok - write standard Java code instead
  • DO NOT use MapStruct - implement mappers manually
  • DO NOT use Mockito - prefer integration testing with TestContainers
  • DO NOT use H2 - use MySQL instead

Architectural Patterns

Package Structure

com.example.bookstore/
├── config/         # Application configuration
├── controller/     # REST controllers and web controllers
├── dto/            # Data Transfer Objects
├── exception/      # Custom exceptions
├── mapper/         # Manual DTO-Entity mappers
├── model/          # Domain entities
├── repository/     # Data access layer
└── service/        # Business logic

Layered Architecture

The application follows a strict layered architecture with a clear flow of control:

  • Controller Layer: Handles HTTP requests, delegates to services
  • Service Layer: Contains business logic, coordinates operations
  • Repository Layer: Manages data access and persistence
  • Model Layer: Represents domain entities

The flow of control should always follow the pattern: Controllers -> Services -> Repositories. Each layer should only interact with the layer directly below it. Controllers should never directly access Repositories.

Idiomatic Usage

Controllers

  • Use @RestController for API endpoints
  • Use @Controller for web pages with React
  • Follow RESTful naming conventions for endpoints:
    • Use nouns instead of verbs (e.g., /books instead of /getBooks)
    • Use plural nouns for collections (e.g., /books instead of /book)
    • Use HTTP methods appropriately:
      • GET for retrieving resources
      • POST for creating resources
      • PUT for updating resources
      • DELETE for removing resources
    • Use hierarchical relationships (e.g., /books/{id}/authors)
  • Return appropriate HTTP status codes:
    • 200 OK for successful GET, PUT, PATCH
    • 201 Created for successful POST
    • 204 No Content for successful DELETE
    • 400 Bad Request for client errors
    • 404 Not Found for missing resources
    • 500 Internal Server Error for server errors
  • Validate input using Bean Validation (@Valid)
  • Implement proper error handling with descriptive error messages

Services

  • Implement business logic in service classes
  • Use interfaces for services when appropriate
  • Handle transactions at the service level with @Transactional

Repositories

  • Use Spring Data JDBC repositories
  • Define custom queries with @Query when needed
  • Keep repository methods focused on data access

DTOs

  • Use DTOs for API requests and responses
  • Implement manual mapping between DTOs and entities
  • Keep DTOs immutable when possible

Common Pitfalls to Avoid

  1. Anemic Domain Model: Ensure entities contain behavior, not just data
  2. N+1 Query Problem: Be mindful of query performance with relationships
  3. Excessive Layering: Don't create unnecessary abstraction layers
  4. Tight Coupling: Use dependency injection to maintain loose coupling
  5. Inconsistent Error Handling: Use a global exception handler
  6. Lack of Validation: Always validate input data
  7. Ignoring Transactions: Be explicit about transaction boundaries

Stylistic Preferences

Naming Conventions

  • Classes: PascalCase, descriptive nouns (e.g., BookController)
  • Methods: camelCase, verb phrases (e.g., findAllBooks())
  • Variables: camelCase, descriptive (e.g., availableBooks)
  • Constants: UPPER_SNAKE_CASE (e.g., MAX_BOOK_LIMIT)

Code Style

  • Use 4 spaces for indentation
  • Maximum line length of 120 characters
  • Group related methods together
  • Order class members: constants, fields, constructors, methods
  • Prefer constructor injection over field injection
  • Use Java's built-in functional interfaces when appropriate

Documentation

  • Document public APIs with Javadoc
  • Include purpose, parameters, return values, and exceptions
  • Keep comments up-to-date with code changes
  • Use meaningful commit messages

Testing Guidelines

  • Write unit tests for services and utilities
  • Write integration tests for repositories using TestContainers
  • Write end-to-end tests for controllers
  • Test both happy paths and edge cases
  • Use descriptive test method names (e.g., shouldReturnAllBooksWhenFindAllIsCalled)
  • Prefer real dependencies over mocks
  • Use appropriate assertions for validation

Database Guidelines

  • Use meaningful table and column names
  • Define appropriate indexes for performance
  • Use migrations for schema changes
  • Keep database interactions efficient
  • Use appropriate data types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment