Enterprise JavaBeans (EJB) and CDI
Domain 4 separates two component models that look alike: EJB session beans with container-managed services, and CDI beans with typesafe injection, qualifiers and events. The exam asks which annotation belongs to which model and what the container does at deployment.
EJB 3.2
- @Stateless beans are pooled with no conversational state; @Stateful beans are one instance per client with @PrePassivate and @PostActivate; @Singleton supports @Startup, @DependsOn and @Lock, with WRITE as the default lock; @MessageDriven consumes messages.
- Lifecycle callbacks are @PostConstruct and @PreDestroy. @Asynchronous returns void or Future, and @Schedule creates calendar-based timers.
- Views are @Local, @Remote, or the no-interface view when no interface exists. @EJB injects; lookups use java:module, java:app or java:global.
- EJB 3.2 Lite, the Web Profile subset, excludes remote views, timers, async methods, MDBs and JAX-WS endpoints.
CDI 1.1
- @Inject resolves by type, then qualifiers, then @Alternative with @Priority; @Named exposes a bean to EL.
- Scopes: @Dependent (default), @RequestScoped, @SessionScoped, @ApplicationScoped, and @ConversationScoped controlled by Conversation.begin() and end().
- Producers (@Produces) supply non-bean types, @Disposes cleans up, @Observes receives events fired through Event.fire(), and interceptors bind with @InterceptorBinding plus @AroundInvoke.
- In beans.xml, discovery-mode annotated enables only bean-defining annotations; all remains the default.
Worked example
Two implementations of PaymentGateway exist and an injection point typed @Inject PaymentGateway fails deployment as ambiguous. Adding @CreditCard and @PayPal qualifiers to the implementations and to the injection point resolves it; declaring one implementation as a selected @Alternative is the other valid answer.
Traps
- Injecting into a private final field or a class without a no-arg constructor, which CDI cannot proxy.
- Using @EJB for a plain CDI bean that has no bean-defining annotation.
- Forgetting that @Dependent beans are never shared, so state vanishes between injection points.