AGENTS.md 3.4 KB

AGENTS.md

Spring Boot 3.5 / Java 17 OJ backend template. Root project is serve (see settings.gradle.kts), Java package space.anyi.serve. Stack and API docs are in README.md; this file only covers non-obvious gotchas.

Commands

  • Run: ./gradlew bootRun (serves on :8080)
  • Test: ./gradlew test (JUnit Platform). No lint/format/typecheck or CI config exists.

Runtime prerequisites

  • Startup requires env vars databaseHost, databaseUsername, databasePassword — missing any makes the app fail on first DB access. No local dev defaults are provided.
  • DB is named oj, all tables live in the dev schema. Initialize via psql -U <user> -f sql/postgersql.sql (note the misspelled filename postgersql.sql).
  • The contextLoads test spins up the full context and needs a live PostgreSQL; it fails without one.

Architecture & conventions

  • Every controller returns the Response<T> wrapper (Response.ok / Response.error). Validation failures map to HTTP 400; other uncaught exceptions return HTTP 200 with an error body (see GlobalExceptionHandler).
  • Auth is stateless JWT in Authorization: Bearer <token>. Roles are stored as plain user/coach/admin in the DB, but method-level auth requires the ROLE_ prefix — JwtAuthenticationFilter adds it, so write @PreAuthorize("hasRole('ROLE_admin')"). Only /auth/login, /auth/register, and swagger paths are public.
  • No Lombok. Entities/DTOs use hand-written getters/setters; controllers use @Resource injection, services use constructor injection.
  • Status/enum values are defined as public static final constants in the entity class they belong to (e.g. User.ROLE_ADMIN, Contest.STATUS_RUNNING, Submission.STATUS_AC, Problem.DIFFICULTY_EASY). Use those constants instead of hardcoded string/number literals everywhere in Java code. Exception: SpEL annotation strings (@PreAuthorize("hasRole('ROLE_admin')")), the "ROLE_" + role authority-prefix concatenation, Swagger @Schema/@Parameter description text, and MyBatis XML (which cannot reference Java constants, e.g. status = 'AC' in SubmissionMapper.xml) keep literals — when adding a literal to a mapper XML, mirror the matching entity constant and keep the value in sync.
  • MyBatis-Plus has a global logic-delete field (deleteFlag), so deletes are logical. Entities target schema-qualified tables via @TableName("dev.user"). Mapper XML lives in src/main/resources/mapper/.
  • JWT secret is a hardcoded base64 key in JwtTokenProvider, 24h expiry, using the jjwt 0.12 API (verifyWith/parseSignedClaims).
  • Swagger UI: /swagger-ui/index.html.

Coding style

  • Controller methods take concrete DTOs for request bodies/params (e.g. UserDto, LoginDto) and return concrete VOs for responses (e.g. UserVo), never raw User entities or generic maps.
  • OpenAPI annotations are mandatory on APIs and models: @Tag/@Operation on controllers and methods, and @Schema on both request DTOs and response VOs (class-level and per-field). Follow the existing DTO/VO examples.
  • Depend on abstractions, not implementations: controllers inject the service interface (UserService), implementations live in service/impl/ (UserServiceImpl). Don't let controllers reference impl classes directly.

Workflow

  • Active branch is oj. Commit messages use the # feat: ... / # sql: ... prefix style from git log.
  • Commit after every completed feature point (each feature is a separate version-control checkpoint).