Modern Jakarta EE Rules
Jakarta EE 10+ namespace migration, modular architecture, and platform conventions.
# CLAUDE.md — Modern Jakarta EE
## Version baseline
- Jakarta EE 10 (or 11). Java 21.
- All `javax.*` packages are renamed to `jakarta.*`. Do the migration once, completely. Mixed namespaces won't link.
- Pick a runtime: WildFly, Open Liberty, Payara, Glassfish. Stay current — old Java EE versions are not Jakarta EE 10.
## Architecture
- Layered: presentation (REST, Servlets) → service (CDI beans) → persistence (JPA).
- Use **CDI** as the central glue. Don't reach for EJBs in new code unless you specifically need transactions, timers, or remoting.
- Keep beans single-responsibility. A `@Stateless` bean with 30 methods is a refactor candidate.
## Modules
- Jakarta EE specs are now Maven artifacts under `jakarta.*` group IDs:
- `jakarta.platform:jakarta.jakartaee-api:10.0.0` (compile-only API)
- Don't bundle the API in your WAR. The runtime provides it.
- Use **MicroProfile** alongside Jakarta EE for cloud-native concerns (config, health, metrics) — it complements rather than replaces.
## Packaging
- WAR for web apps. EAR only when you genuinely need multiple modules with isolated classloaders.
- Skinny WAR + provided dependencies — let the runtime supply the platform classes.
- `pom.xml`:
```xml
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
```
## Deployment descriptors
- Prefer annotations over `web.xml` / `ejb-jar.xml`. They survive refactors better.
- Use descriptors only for declarative things annotations can't express well (security roles in some contexts, JNDI overrides).
- Don't have both — pick a primary source. `metadata-complete="true"` to disable annotation scanning if descriptors are authoritative.
## Logging
- **java.util.logging** is the platform default but inconvenient. Use **SLF4J + Logback** (or whatever your runtime supplies, e.g., WildFly's logging).
- Configure structured JSON output for production observability stacks.
## Testing
- **Arquillian** for integration tests against a real container. Slower than unit tests but realistic.
- For unit tests, use plain JUnit 5 + Mockito. Most beans don't need a container to test.
## Don't
- Don't write new code against Java EE 8. Migrate to Jakarta EE 10+.
- Don't deploy multiple WARs that share state via static singletons. Use a JNDI-bound resource or a shared library.
- Don't `@PersistenceContext` into a `@RequestScoped` bean and expect lazy loading to work after the request ends.
- Don't pick Jakarta EE for a single-purpose microservice that doesn't use the platform features. Spring Boot or Quarkus is usually a better fit.
Other Jakarta EE templates
Modern Quarkus Rules
Quarkus 3+ defaults: dev mode, build-time optimization, configuration, and CDI.
Quarkus REST (RESTEasy Reactive)
JAX-RS endpoints with RESTEasy Reactive — request validation and response models.
Quarkus + Hibernate ORM with Panache
Active-record and repository styles with Panache, Flyway migrations, transactions.
Jakarta CDI
CDI scopes, qualifiers, producers, events, and the lifecycle to actually understand.
Jakarta Persistence (JPA)
Entities, fetch strategies, JPQL, transactions, and L2 cache discipline.