Java EE 7 Application Developer common mistakes
Java EE 7 Application Developer · Understand the traps and how to avoid them.
Assuming that an @Stateless or @Singleton bean instance is shared across all clients and storing per-client conversational state in instance fields.
Candidates confuse EJB pooling semantics with servlet threading: stateless beans are pooled and any instance may serve any call, while singletons are shared. The exam tests whether you know that only @Stateful beans keep conversational state, and that @Singleton fields need explicit concurrency protection.
What to do instead
Use @Stateful with @ConversationScoped or session-scoped CDI beans for per-client state; keep stateless/singleton beans stateless. For singleton mutable state, add @Lock(LockType.WRITE) or @ConcurrencyManagement(CONCURRENCY_MANAGEMENT_TYPE.BEAN) and guard fields yourself.
Treating container-managed transaction boundaries as if every EJB method starts a new transaction, or expecting a REQUIRED method to see uncommitted changes after a caught exception.
The default is REQUIRED, which joins an existing transaction; only REQUIRES_NEW suspends it. Also, a RuntimeException marks the transaction rollback-only even if the caller catches it, so later work silently fails at commit.
What to do instead
Map each attribute explicitly: REQUIRED joins, REQUIRES_NEW suspends, MANDATORY requires, NEVER forbids, SUPPORTS adapts, NOT_SUPPORTED suspends. Remember EJBException and runtime exceptions force rollback unless @ApplicationException(rollback=false); handle checked exceptions instead, or call setRollbackOnly deliberately.
Expecting a JPA entity with a generated identity or a lazy association to behave the same outside a transaction, or assuming merge() on a detached entity updates the database immediately.
Entities become detached when the persistence context closes; lazy collections then throw LazyInitializationException. merge() returns a managed copy and only flushes at transaction commit or explicit flush, and identity generation requires a database round trip that may not be available before flush.
What to do instead
Fetch needed associations with JOIN FETCH or EntityGraph inside the transaction, or use an extended persistence context for conversational state. Use merge() and treat its return value as the managed instance; call flush() when you need the generated key immediately, and prefer SEQUENCE or TABLE generators for pre-allocation.
Relying on field access and property access interchangeably in one entity hierarchy, or putting @Id on a field while annotating getters elsewhere.
JPA determines access type from the placement of @Id (or @Access) and applies it consistently across the hierarchy; mixing placements without @Access leads to ignored mappings or startup errors. Candidates often copy snippets that mix styles.
What to do instead
Choose one style per entity and hierarchy: annotate fields or getters, not both. If you must switch, place @Access(AccessType.PROPERTY) on the class or specific members, and keep @Id placement consistent with the chosen strategy.
Mixing @Path, @QueryParam, @FormParam and @Consumes annotations incorrectly, e.g. expecting @QueryParam to read a JSON body or @FormParam to work without application/x-www-form-urlencoded.
Each annotation binds a different part of the HTTP request, and the exam presents realistic-looking methods where the wrong binding compiles but silently yields null. Form parameters require the form media type, and entity bodies require a MessageBodyReader.
What to do instead
Use @PathParam for URI template variables, @QueryParam for the query string, @FormParam only with application/x-www-form-urlencoded or multipart, @HeaderParam/@CookieParam for headers and cookies, and an unannotated parameter for the entity body with matching @Consumes. Verify @Produces matches the returned media type.
Assuming a JAX-RS resource class is a singleton, or that @Singleton/@Stateless injection scopes are interchangeable with the default per-request lifecycle.
By default a root resource is instantiated per request, so instance fields do not persist between calls; candidates who store state there see lost data. Conversely, marking a resource @Singleton introduces concurrency concerns the exam probes.
What to do instead
Keep root resources stateless or delegate to CDI/EJB beans. If you need shared state, use @Singleton with thread-safe structures or an EJB @Singleton with proper locking, and remember sub-resource locators return objects whose lifecycle you control.
Confusing JSF request processing phases and putting validation or model updates in the wrong listener, or expecting immediate="true" to skip validation.
The six phases (restore view, apply request values, process validations, update model values, invoke application, render response) determine when converters, validators and action methods run. immediate="true" moves action invocation to apply request values, bypassing later validation, which candidates misread as 'skip validation only'.
What to do instead
Memorize phase order and what each phase does. Use immediate="true" for cancel buttons and login-style actions that must bypass validation, place cross-field checks in a custom validator or action method, and use <f:ajax execute="@this" render="..."> to control which components are processed.
Mixing JSF managed-bean annotations with CDI annotations, or expecting @ManagedBean and @Named to be equivalent.
JSF 2.2 deprecated @ManagedBean in favor of CDI, but both appear in older material. @ManagedBean uses the JSF injection model and does not support CDI features such as @Inject, interceptors or @ConversationScoped; @Named alone does not make a bean a JSF backing bean without a scope.
What to do instead
Use CDI: @Named plus a CDI scope such as @RequestScoped, @ViewScoped (javax.faces.bean.ViewScoped in JSF, or CDI-compatible equivalents), @SessionScoped or @ConversationScoped, with @Inject for dependencies. Reserve @ManagedBean for legacy code you cannot change.
Writing servlet or filter mappings that conflict, or assuming a filter's doFilter() continues the chain automatically.
URL patterns follow specific precedence (exact, then longest path prefix, then extension, then default), and filters must call chain.doFilter() to pass the request along. Forgetting it produces a blank response; ordering filters wrongly breaks authentication or encoding.
What to do instead
Use exact or path mappings deliberately, remember / and /* have different meanings, and always call chain.doFilter(request, response) unless intentionally short-circuiting. Control filter order with @WebFilter or web.xml ordering, and set request encoding before reading parameters.
Misconfiguring JAX-WS endpoints or security constraints: expecting a plain POJO with @WebService to be deployed without a container, or assuming @RolesAllowed on a servlet works without a matching security-constraint.
JAX-WS endpoints need a servlet container or EJB container to publish them, and @RolesAllowed is enforced by the EJB container or by the web container only when declarative security and a login mechanism are configured. Candidates also forget that web service clients need the WSDL or a generated port.
What to do instead
Deploy @WebService classes as servlets (web.xml) or session beans, and publish with Endpoint.publish only for standalone use. For security, declare , and in web.xml, or use @DeclareRoles/@RolesAllowed on EJBs, and test with a configured realm.