This file provides guidance to any AI agents when working with code in this repository.
When guidance conflicts, use this order:
- Explicit user or task instructions in the current conversation.
- This file (
AGENTS.md). - The module-level
README.md. - Existing conventions in the files being changed.
CLAUDE.md points to this file and adds no rules.
Bootstrap provides opinionated services and components for Spring Boot projects. It uses Java 17, Spring Boot 3.5.x,
and Apache Maven. The root pom.xml is a multi-module reactor with packaging=pom. There is no CI pipeline; verify
builds and tests manually.
Module groups (each has its own pom.xml):
base: app, cli, configuration, core, feature, logger, metrics, registry, resource, security, store, support, test, trace, webdata: broker, content (Apache Tika), dataset, dsv, jdbc (incl. modular DB migration), model, testextension: dos, help, mail, rest-api, rest-api-client (Retrofit), search, security, support, system, template (Thymeleaf), test, webcloud: googleai: api, core, lucene, provider (github, hugging-face, llama, ollama, openai), webserenity: browser testing on Serenity BDDdemo: runnable Spring Boot demo app (DemoApplication)bom: Bill of Materials for dependency management
The root pom.xml depends on sibling net.microfalx artifacts (lang, resource, metrics, tracing, jvm,
jdbcpool, threadpool, and webjar) from separate repositories. It also uses the external parent POM
net.microfalx:pom and the centralized net.microfalx:bom for dependency management.
mvn clean install -DskipTests— compile/install the whole reactor without tests.mvn clean test— compile and run tests.mvn -pl <module> -am test— run tests for a single module and its dependencies.mvn -pl <module> -Dtest=ClassName#methodName test— run a single test method.- Minimum verification before considering a change complete:
- Docs-only change: no build required.
- Single-module code change:
mvn -pl <module> -am test. - Change touching shared/core modules or public APIs:
mvn clean testfor the whole reactor.
- Run the demo app with
mvn spring-boot:runfrom thedemomodule, or run theDemoApplicationmain class. It serves at http://localhost:8080. - The demo app requires a local MySQL database. See
README.mdfor setup commands. It uses in-house migrations; see the Database access section below.
- No enforced commit message. Write clear, descriptive commit messages summarizing the change and its intent. See "Build & test" for the required verification level before committing.
- Branching follows the MAJOR.MINOR versioning scheme. Use
mainfor the latest development version. Usex.yfor release branches.
- Indentation: 4 spaces.
- Blank lines: use to separate logical blocks of code.
- Line length: maximum 120 characters.
- Use IntelliJ IDEA default code style for Java.
Follow standard Java/Spring Boot conventions except where overridden below.
- Use UTF-8 encoding.
- Use descriptive names for classes, methods, and variables.
- Avoid
varkeyword, prefer explicit types, for consistent, easily-reviewable diffs; unless the line is very long and the type is obvious from the right-hand side. - Prefer immutability. Avoid mutating shared/external state inside
for-eachloops orStream.forEach()/peek(). Usemap/filter/collector build a new collection instead. - Avoid magic numbers and strings; use constants instead.
- Check emptiness and nullness before operating on collections and strings. Use project-internal
net.microfalx.lang.StringUtilsandnet.microfalx.lang.ObjectUtils, not Apache Commons or Guava. - Comment complex or non-obvious business logic; keep comments clear and concise. For public classes/methods
exposed as module APIs (
publictypes outsideinternal/implpackages), use Javadoc instead of a plain comment; not required for internal/package-private code. - Use
@Overridewhen overriding methods. - Wrap 2 or more boolean conditions (e.g., in an
if) into a named boolean variable describing the intent, instead of an inline compound expression. - Prefer early returns; avoid
elsewhen a return can be used instead. - Use immutability objects with builder pattern objects for API domain objects based on
net.microfalx.lang.IdentityAware.Builderor one of the subclasses depending on which subclass ofnet.microfalx.lang.IdentityAwareis created.
- Use
@RequiredArgsConstructorfor dependency injection via constructor. - Use
@Slf4jfor logging. The repository configures the logger field asLOGGER; seelombok.config. - Use
@Builder(setterPrefix = "with")for complex object creation. - Avoid
@Dataannotation; prefer@Getter,@Setter, and@ToStringfor granular control.
@Service: for business logic classes.@Repository: for data access classes that extend JPA repositories or interact with the database.@Controller: for web controllers.@RestController: for REST API controllers.@Component: for generic Spring components.@Configuration: for Spring configuration classes.- Use constructor injection with
@RequiredArgsConstructorandfinalfields. Do not use field injection except in tests. - Use
@ConfigurationPropertiesto bind related properties. Prefer it over multiple@Valueannotations for 3 or more properties. @Transactional: only on@Serviceclasses. Justify each use and ensure rollback covers the failure cases.- Avoid circular dependencies. Do not use
@Orderto mask a circular-dependency problem.@Orderis fine for legitimate bean-ordering (e.g.,@Order(Ordered.HIGHEST_PRECEDENCE)on infrastructure services).
- Modules must not introduce circular dependencies across the reactor. A module may depend only on modules earlier in
its group or on groups it legitimately builds on. Check the root
pom.xmlmodule order. - When adding a new dependency between modules, prefer depending on an API/interface module over an implementation module, if one exists.
- Do not add new dependencies; Provide reasons why new dependencies are needed.
- Use
net.microfalx.bootstrap.model.Mapperwhich provides a generic mapping framework for converting between domain objects and DTOs. It supports mapping between different types, including nested objects and collections. - Use
net.microfalx.bootstrap.model.Mapper.toto create a new target object and copy properties from the source object. - Use
net.microfalx.bootstrap.model.Mapper.copyto create copy properties from the source object into an existing target object. - Use
net.microfalx.bootstrap.model.Mapper.builderto create builder and customize the mapping (when the property names are not the same) usingignoreField,ignoreAnnotation,mapFieldin the builder class.
- Avoid
throwsclauses; prefer unchecked exceptions for domain/service APIs. Keep checked exceptions only when required by an external API/contract. - Each module defines one root exception extending
RuntimeException(e.g.AiException,ResourceException,CliException). More specific exceptions extend the module's root exception, notRuntimeExceptiondirectly (e.g.AiNotFoundException extends AiException). - Use
@RestControllerAdviceand@ExceptionHandlerfor global exception handling on@RestControllers (seenet.microfalx.bootstrap.restapi.RestApiExceptionHandler). Reserve plain@ControllerAdvicefor view-based@Controllererror handling, if ever needed. - Map exceptions to appropriate HTTP status codes in REST controllers.
- Reuse/extend
net.microfalx.bootstrap.restapi.RestApiErrorfor error responses instead of introducing a new shape per module.
Frameworks:
- JUnit 5 for unit and integration tests.
- Plain JUnit assertions for simple cases; AssertJ (
org.assertj.core.api.Assertions) for complex assertions. - Plain Mockito for utility and domain unit tests that do not need a Spring Boot context.
ServiceUnitTestCasefor service/component unit tests (seenet.microfalx.bootstrap.test.ServiceUnitTestCase). It supports the Mockito extension and custom answers via classes annotated with@AnswerFor(seenet.microfalx.bootstrap.test.annotation.AnswerFor).ServiceIntegrationTestCasefor integration tests (seenet.microfalx.bootstrap.test.ServiceIntegrationTestCase). It already imports core configurations and services.
Conventions:
- Use given/when/then structure in test methods.
- Do not prefix test method names with
test. Use descriptive camelCase names indicating the behavior tested (e.g.,getUserByIdOk,getUserByIdNotFound). - Avoid reflection in tests when possible.
- Avoid business logic in tests; focus on behavior verification.
- Use
@Slf4jannotation from Lombok for logging to avoid boilerplate code with Logger instances. - Log at appropriate levels:
DEBUG,INFO,WARN,ERROR. - Include contextual information in logs (e.g.,
requestId,userId,entityId,operation,outcome). - Avoid logging sensitive information.
- Use structured logging for better log management.
- Format log messages with placeholders (e.g.,
{}) instead of string concatenation.
- Prefer Spring Data JPA in this order: repository methods, JPQL
@Query, short native@Query, thenQueryProvider.- CRUD/simple filter -> JPA repository methods.
- Medium-complexity portable query -> JPQL
@Query. - DB-specific but short -> native
@Query. - Large (upserting, multiple joins, etc.), dynamic, or vendor-specific ->
QueryProvider+ SQL resource file.
- Schema is defined in
resources/sql/TYPE/schemaand data inresources/sql/TYPE/data; both run automatically at application startup (TYPE=mysql,postgres, etc.; default target database is MySQL). - Custom native queries live in
resources/sql/TYPE/queriesand run vianet.microfalx.bootstrap.jdbc.support.Query(built on Spring BootJdbcClient) andnet.microfalx.bootstrap.jdbc.support.QueryProvider. - Use transactions for operations that modify the database and ensure proper rollback on exceptions.
- Avoid N+1 query problems; use fetch joins or
@EntityGraph.