|
| 1 | +# Enterprise Java and framework practices |
| 2 | + |
| 3 | +Apply this guide only when the corresponding framework is present. The Java |
| 4 | +compilation target, Jakarta EE platform level, MicroProfile version, Spring |
| 5 | +generation, provider capabilities, and database support are independent |
| 6 | +compatibility axes. Detect each from build dependencies and deployment |
| 7 | +configuration before recommending a migration. |
| 8 | + |
| 9 | +## Migration boundaries |
| 10 | + |
| 11 | +- Preserve transaction boundaries, security constraints, retries, delivery |
| 12 | + guarantees, persistence behavior, observability, and container lifecycle. |
| 13 | + Replacing annotations is not proof of equivalent behavior. |
| 14 | +- Treat `javax.*` to `jakarta.*` as an ecosystem migration. Verify the runtime, |
| 15 | + dependencies, generated sources, descriptors, tests, and integrations move |
| 16 | + together; do not mix the namespaces in one application. |
| 17 | +- Prefer constructor injection for required dependencies when the framework |
| 18 | + supports it. Use field or resource injection only where the container contract |
| 19 | + requires it. |
| 20 | +- Confirm native-image/AOT, reflection, proxying, serialization, and build-time |
| 21 | + indexing constraints before changing frameworks or component models. |
| 22 | + |
| 23 | +## Jakarta component model |
| 24 | + |
| 25 | +- Prefer CDI scopes and `@Inject` for ordinary application services over EJB |
| 26 | + session beans, and use `@Transactional` when its interceptor semantics match. |
| 27 | + Keep EJB where remote interfaces, passivation, asynchronous methods, timers, |
| 28 | + pooling, or other EJB services are required. |
| 29 | + <!-- covers: ejb-vs-cdi singleton-ejb-vs-cdi-application-scoped --> |
| 30 | +- Replace JNDI service-locator code with typed injection for managed resources, |
| 31 | + but retain explicit lookup at genuine dynamic naming boundaries. |
| 32 | + <!-- covers: jndi-lookup-vs-cdi-injection --> |
| 33 | +- Prefer CDI `@Named` beans to legacy JSF managed beans. Verify scopes, proxy |
| 34 | + requirements, serialization, and view lifetime during migration. |
| 35 | + <!-- covers: jsf-managed-bean-vs-cdi-named --> |
| 36 | +- Prefer declarative `@Transactional` boundaries at service methods over manual |
| 37 | + transaction choreography. Keep explicit transactions when one method truly |
| 38 | + needs multiple independently controlled units of work, and account for |
| 39 | + self-invocation and rollback rules. |
| 40 | + <!-- covers: manual-transaction-vs-declarative --> |
| 41 | +- Use Jakarta Concurrency managed executors rather than application-created |
| 42 | + threads in a Jakarta runtime. Do not replace persistent, calendar-based EJB |
| 43 | + timers with an in-memory fixed-rate schedule unless restart, clustering, |
| 44 | + misfire, timezone, and exactly-once requirements permit it. |
| 45 | + <!-- covers: ejb-timer-vs-jakarta-scheduler --> |
| 46 | + |
| 47 | +## HTTP APIs and messaging |
| 48 | + |
| 49 | +- Prefer Jakarta REST resources for resource-oriented HTTP APIs over low-level |
| 50 | + servlet dispatch code. Keep filters, streaming, protocol upgrades, and other |
| 51 | + servlet-level behavior where those APIs are the right abstraction. |
| 52 | + <!-- covers: servlet-vs-jaxrs --> |
| 53 | +- Prefer REST/JSON over SOAP only when contracts, WS-Security, reliable |
| 54 | + messaging, transactions, schema-first tooling, and client compatibility do |
| 55 | + not require the WS-* stack. Modernize the contract, not merely the transport. |
| 56 | + <!-- covers: soap-vs-jakarta-rest --> |
| 57 | +- Consider MicroProfile Reactive Messaging for channel-based event processing, |
| 58 | + typed payloads, and backpressure. Before replacing an MDB, match JMS |
| 59 | + acknowledgement, ordering, redelivery, dead-letter, transaction, selector, |
| 60 | + and concurrency semantics and verify the chosen connector. |
| 61 | + <!-- covers: mdb-vs-reactive-messaging --> |
| 62 | + |
| 63 | +## Persistence choices |
| 64 | + |
| 65 | +- Use JPA for aggregate-oriented persistence and managed entity lifecycles; use |
| 66 | + JDBC when exact SQL, low overhead, bulk operations, or database-specific |
| 67 | + control is more important. Account for lazy loading, fetching, locking, |
| 68 | + batching, caching, and transaction scope rather than assuming ORM is simpler. |
| 69 | + <!-- covers: jdbc-vs-jpa --> |
| 70 | +- Use the JPA Criteria API for genuinely dynamic entity queries. It is not fully |
| 71 | + type-safe when attributes are referenced by strings; use the static metamodel |
| 72 | + or another typed query approach when compile-time attribute checking matters. |
| 73 | + <!-- covers: jdbc-resultset-vs-jpa-criteria --> |
| 74 | +- Consider jOOQ when SQL is the primary abstraction and generated schema types, |
| 75 | + CTEs, window functions, vendor features, and composable queries matter. |
| 76 | + Verify edition/database support, code generation, dialect behavior, and |
| 77 | + transaction integration. Continue binding all untrusted values. |
| 78 | + <!-- covers: jdbc-vs-jooq --> |
| 79 | +- Prefer Jakarta Data repositories for conventional CRUD and derived queries |
| 80 | + when the Jakarta EE 11 runtime and provider implement the required behavior. |
| 81 | + Retain `EntityManager`, criteria, or SQL for complex persistence operations, |
| 82 | + and verify query derivation, pagination, locking, and transaction semantics. |
| 83 | + <!-- covers: jpa-vs-jakarta-data --> |
| 84 | + |
| 85 | +## Spring |
| 86 | + |
| 87 | +- Prefer annotation-based configuration, constructor injection, and focused |
| 88 | + explicit `@Configuration` over large XML bean graphs in modern Spring. |
| 89 | + Preserve XML where externalized wiring or legacy integration makes it useful; |
| 90 | + do not rely on broad component scanning that obscures ownership. |
| 91 | + <!-- covers: spring-xml-config-vs-annotations --> |
| 92 | +- On Spring Framework 7, use native API version conditions when they match the |
| 93 | + public versioning strategy. Keep version negotiation centralized, document |
| 94 | + deprecation and compatibility policy, and avoid merging unrelated versions |
| 95 | + into a controller merely to reduce class count. |
| 96 | + <!-- covers: spring-api-versioning --> |
| 97 | +- On Spring Framework 7, migrate Spring nullness annotations to JSpecify |
| 98 | + deliberately. Establish `@NullMarked` boundaries, annotate type uses |
| 99 | + accurately, configure a checker, and treat diagnostics as migration work |
| 100 | + rather than suppressing them. |
| 101 | + <!-- covers: spring-null-safety-jspecify --> |
0 commit comments