Java Coding Standards
Standards for readable, maintainable Java (17+) code in Spring Boot services.
When to Activate
- •Writing or reviewing Java code in Spring Boot projects
- •Enforcing naming, immutability, or exception handling conventions
- •Working with records, sealed classes, or pattern matching (Java 17+)
- •Reviewing use of Optional, streams, or generics
- •Structuring packages and project layout
Core Principles
- •Prefer clarity over cleverness
- •Immutable by default; minimize shared mutable state
- •Fail fast with meaningful exceptions
- •Consistent naming and package structure
Naming
java
// ✅ Classes/Records: PascalCase
public class MarketService {}
public record Money(BigDecimal amount, Currency currency) {}
// ✅ Methods/fields: camelCase
private final MarketRepository marketRepository;
public Market findBySlug(String slug) {}
// ✅ Constants: UPPER_SNAKE_CASE
private static final int MAX_PAGE_SIZE = 100;
Immutability
java
// ✅ Favor records and final fields
public record MarketDto(Long id, String name, MarketStatus status) {}
public class Market {
private final Long id;
private final String name;
// getters only, no setters
}
Optional Usage
java
// ✅ Return Optional from find* methods
Optional<Market> market = marketRepository.findBySlug(slug);
// ✅ Map/flatMap instead of get()
return market
.map(MarketResponse::from)
.orElseThrow(() -> new EntityNotFoundException("Market not found"));
Streams Best Practices
java
// ✅ Use streams for transformations, keep pipelines short
List<String> names = markets.stream()
.map(Market::name)
.filter(Objects::nonNull)
.toList();
// ❌ Avoid complex nested streams; prefer loops for clarity
Exceptions
- •Use unchecked exceptions for domain errors; wrap technical exceptions with context
- •Create domain-specific exceptions (e.g.,
MarketNotFoundException) - •Avoid broad
catch (Exception ex)unless rethrowing/logging centrally
java
throw new MarketNotFoundException(slug);
Generics and Type Safety
- •Avoid raw types; declare generic parameters
- •Prefer bounded generics for reusable utilities
java
public <T extends Identifiable> Map<Long, T> indexById(Collection<T> items) { ... }
Project Structure (Maven/Gradle)
code
src/main/java/com/example/app/ config/ controller/ service/ repository/ domain/ dto/ util/ src/main/resources/ application.yml src/test/java/... (mirrors main)
Formatting and Style
- •Use 2 or 4 spaces consistently (project standard)
- •One public top-level type per file
- •Keep methods short and focused; extract helpers
- •Order members: constants, fields, constructors, public methods, protected, private
Code Smells to Avoid
- •Long parameter lists → use DTO/builders
- •Deep nesting → early returns
- •Magic numbers → named constants
- •Static mutable state → prefer dependency injection
- •Silent catch blocks → log and act or rethrow
Logging
java
private static final Logger log = LoggerFactory.getLogger(MarketService.class);
log.info("fetch_market slug={}", slug);
log.error("failed_fetch_market slug={}", slug, ex);
Null Handling
- •Accept
@Nullableonly when unavoidable; otherwise use@NonNull - •Use Bean Validation (
@NotNull,@NotBlank) on inputs
Testing Expectations
- •JUnit 5 + AssertJ for fluent assertions
- •Mockito for mocking; avoid partial mocks where possible
- •Favor deterministic tests; no hidden sleeps
Remember: Keep code intentional, typed, and observable. Optimize for maintainability over micro-optimizations unless proven necessary.