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 Java templates
Modern Java Rules
Java 21+ defaults: records, sealed types, pattern matching, virtual threads, var.
Java Testing with JUnit 5
JUnit 5 + AssertJ + Mockito + Testcontainers — opinionated test conventions.
Java Virtual Threads & Concurrency
Project Loom virtual threads, structured concurrency, and modern concurrent patterns.
Java Build (Maven & Gradle)
Build conventions, dependency management, multi-module projects, and CI patterns.
Java Streams & Collections
Streams API, immutable collections, Collectors, and idiomatic data manipulation.