SLIDE 1 S E S S I O N 2 0 1 8 1
PATTERNS & BEST PRACTICES FOR CDI
Ryan Cuprak
e-Formulation Analyst, Author, Connecticut Java Users Group President
Reza Rahman
Resin Developer, Java EE/EJB/JMS JCP expert, Author EJB 3 in Action
SLIDE 2 AGENDA
- CDI Overview
- XML Configuration vs.
Annotations
- Qualifiers
- Naming
- Scoping
- Stereotypes
- Inceptors &
Decorators
Resource Injection
- CDI Integration
- EJB
- JSF
- JPA
- Extensions
- Conclusion
- Q&A
SLIDE 3 OVERVIEW
- What is CDI?
- Dependency injection standard for Java EE.
- Based on Seam 2, Google Guice, and Spring.
- Defined in JSR-299.
- Why CDI?
- Improve Java EE dependency injection support.
- Provide a standard DI for both enterprise and web
applications.
- Provide a Java-centric type safety injection using
annotations.
- As adoption grows, it is important to understand
how to leverage CDI effectively.
SLIDE 4 OVERVIEW
- Basic dependency injection:
- @Inject, @Qualifier, @Stereotype, @Alternative, @All, @Any,
@New
- Component naming:
- @Named
- Custom object factories:
- @Produces, @Disposes, InjectionPoint
- Context management:
- @Dependent, @RequestScoped, @SessionScoped,
- @ConversationScoped, @ApplicationScoped, @Scope
SLIDE 5 OVERVIEW
Event, @Observes
@Interceptor, @InterceptorBinding, @AroundInvoke, InvocationContext, @Decorator, @Delegate
SLIDE 6 CONFIGURATION
- CDI is annotation centric:
- Annotations are ideal for type-safe dependency injection.
- Compact, semi-permanent, and semantically close to
code, tools-friendly.
- CDI does support XML configuration (beans.xml):
- Override annotation configuration.
- Perform DI using JRE classes or third-party libraries.
- Plug-ins provide enhanced configuration and behavior
support:
- Seam 3 XML
- CanDI XML
- Some developers prefer XML over annotations.
SLIDE 7 CONFIGURATION
Let’s look at a simple example leveraging XML configuration.
- Pieces:
- DefaultAccountService – EJB stateless session bean.
- DefaultAccountDAO – performs basic CRUD operations
- MockAccountDAO – replaces DefaultAccountDAO for unit
testing.
- @Audited – interceptor used for auditing.
- @Profiled – interceptor collecting profiling data
- Deployments types:
- Unit Testing, Integration Testing, Production
SLIDE 8
XML DEPLOYMENT EXAMPLE
SLIDE 9 UNIT TESTING
META-INF/beans.xml
SLIDE 10 INTEGRATION TESTING
META-INF/beans.xml
SLIDE 11 PRODUCTION
META-INF/beans.xml
SLIDE 12
XML CONFIGURATION
Using the beans-test.xml:
SLIDE 13
OVERRIDE JAVA/ANNOTATION DEFAULTS
Override default values in a bean via XML:
SLIDE 14 WIRING THIRD-PARTY EXTENSIONS
Configure a JRE class for injection, support multiple instances:
new DecimalFormat(“$0.00”);
SLIDE 15
XML OBJECT WIRING
Define MailSender and define two different qualifiers for injecting two difference instances:
SLIDE 16 XML OBJECT WIRING
Configure two instances of MailSender:
SLIDE 17
XML OBJECT WIRING
Injecting the MailSupport MailSender instance:
SLIDE 18 QUALIFIER TYPE-SAFETY VS. VERBOSITY
- Benefits of Qualifiers?
- Type-safe
- Java-centric dependency resolution
- Enhances readability, fluency, maintainability
- Drawbacks:
- Can be verbose
- Qualifiers can be used with enumerations to
reduce verbosity
- Best Practice:
- @Named as Qualifier – should be used sparingly because
they are a lot more brittle.
SLIDE 19
TYPE-BASED QUALIFIERS
@Qualifier @Retention(RUNTIME) @Target({ FIELD, TYPE }) public @interface Admin {} @Qualifier @Retention(RUNTIME) @Target({ FIELD, TYPE }) public @interface Support {} @Inject @Support private MailSender mailSender;
SLIDE 20 QUALIFIERS WITH ENUMERATIONS
Qualifiers with enumerations reduce verbosity:
@Qualifier @Retention(RUNTIME) @Target({ FIELD, TYPE }) public @interface MailSenderType { MailSenderTypes value(); } public enum MailSenderTypes { ADMIN, SUPPORT } @Inject @MailSenderType(MailSenderTypes.SUPPORT) private MailSender mailSender;
SLIDE 21
@NAMED AS QUALIFIER
Named can be used as a Qualifier (brittle): @Named(“admin”) public class AdminMailSender implements MailSender { … } @Named(“support”) public class SupportMailSender implements MailSender { … } @Inject @Named(“support”) private MailSender mailSender;
SLIDE 22 COMPONENT NAMING
Practices when using the @Named annotation:
- String based names not needed for dependency
resolution.
- Only necessary to name components that are
referenced outside of Java such as in JSF/Facelets via EL.
- Default names good enough in most cases.
- Be careful of naming conflicts – name-based
resolution not type-safe!
- Choose names that add to readability/API fluency.
SLIDE 23 SPECIFYING COMPONENT NAMES
Implicit name using class name: @Named @ConversationScoped public class TransferWizard { <h:inputText id="amount” value="#{transferWizard.amount}"/> Explicit name: @Named(“transfer”) @ConversationScoped public class TransferWizard { <h:inputText id="amount" value="#{transfer.amount}"/>
SLIDE 24 COMPONENT SCOPING
What are the scope?
- Fine-grained scopes – @ApplicationScoped,
@SessionScoped, @ConversationScoped, @RequestScoped, @Dependent
- Scoping extensions – @WindowScoped,
@RenderScoped, @ViewScoped, Flash, @TransactionScoped, @ThreadScoped
What are the purposes and best practices?
- Components with appropriate scopes maximize
memory usage.
- Scopes remove boilerplate state maintenance code –
especially at presentation tier.
- Make judicious use of conversations!
SLIDE 25
SCOPE GRANULARITY
SLIDE 26
CONVERSATION SCOPE
SLIDE 27 GROUPING METADATA IN STEREOTYPES
- Components self-organize into roles in well-
architected systems.
- Roles get surfaced as groups of recurring
metadata.
- CDI allows component roles to be articulated as
stereotypes.
- Stereotypes encapsulate specialized behavior and
can be cumulative.
SLIDE 28
STEREOTYPES FOR COMPONENT ROLES
Examples of stereotypes: Dao, Service, Model, Mock, Model. Note: Model is built-in.
SLIDE 29 INTERCEPTORS VS. DECORATORS
- Interceptors and Decorators both geared towards
cross-cutting logic.
- Bypass traditional complexity associated with AOP
by avoiding point-cuts.
- Interceptors are designed for system-level cross-
cutting concerns very decoupled from business logic.
- Decorators intended for concerns that should be
compartmentalized but are still very close to business logic.
SLIDE 30 INTERCEPTOR USAGE
Defining the interceptor:
@InterceptorBinding @Target({TYPE, METHOD}) @Retention(RUNTIME) public @interface Audited {} @Interceptor @Audited public class AuditInterceptor { @AroundInvoke public Object audit(InvocationContext context) throws Exception { System.out.print("Executing: “ + context.getMethod().getName()); System.out.println(" with args: ”+ Arrays.toString(context.getParameters())); return context.proceed(); } }
Using the interceptor:
@Stateless public class DefaultAccountService implements AccountService { ... @Audited public void addAccount(Account account) {
SLIDE 31
DECORATOR USAGE
SLIDE 32 INJECTION AND LOOK-UP
- Declarative, static injection sufficient for most cases
- @Produces, @Disposes used when objects must be
programmatically created/destroyed
- Look-up using Instance used when decencies need
to be resolved at runtime
- For very dynamic resolution,
BeanManager.getBeans SPI can be used
SLIDE 33 PRODUCING OBJECTS AT RUNTIME
@Inject @LoggedIn private User user; @Inject private AccountService accountService; @Named @Produces @SessionScoped @SelectedAccount public Account getCurrentAccount() { return accountService.getAccount(user.getId()); } @Produces public Logger createLogger(InjectionPoint injectionPoint) { return Logger.getLogger(injectionPoint.getMember() .getDeclaringClass().getName()); }
SLIDE 34
DYNAMIC LOOK-UP
@Inject @Holiday private Instance<Discount> discount; ... if (!discount.isUnsatisfied()) { Discount currentDiscount = discount.get(); }
SLIDE 35 DEPENDENCY VS. RESOURCE INJECTION
- Java EE 5 introduced resource injection annotations
- @Resource, @EJB, @PersistenceContext
- Limited, specialized, name-based injection
- Java EE 6 introduces CDI
- Powerful, general purpose, type-safe injection
- Mostly orthogonal functionality, some overlap
- Favor CDI for greater flexibility
SLIDE 36 JAVA EE INJECTION FLAVORS
@Inject private AccountDao accountDao; @Inject // @EJB private AccountService accountService; @Inject // @Resource private UserTransaction userTransaction; @PersistenceContext private EntityManager entityManager; @Resource(name="jdbc/AcmeBankDB") private DataSource dataSource; @Resource(name="jms/TransferQueue") private Queue transferQueue;
SLIDE 37 WHEN TO USE EJB?
- Use EJB for enterprise services – like transactions
- Use CDI managed beans otherwise – EJB does
have overhead
- Avoid plain managed beans
- EJBs most appropriate for service/business logic tier
- CDI makes it possible to use EJBs as JSF managed
beans – only good practice for RAD/prototyping
- Using EJB services without EJB
SLIDE 38
CDI & EJB
SLIDE 39 CDI AND JSF
- CDI more powerful replacement to JSF managed
beans
- Seam Faces excellent enhancement
- CDI naming, scopes, producers, qualifiers work in
powerful ways with JSF
- CDI designed with JSF in mind, but not limited to JSF
– Wicket, Struts 2, Spring MVC, Swing Desktop application.
SLIDE 40
CDI & JSF
SLIDE 41
CDI & JSF
SLIDE 42 CDI AND JPA
- CDI/JPA bean life-cycle mismatch
- Life-cycle mismatch can be bridged by CDI
producers
- Make judicious use of stateful session bean
extended persistence context
SLIDE 43
PRODUCING ENTITY BEANS
SLIDE 44 USING PORTABLE EXTENSIONS
- Portable extensions perhaps most important part of
CDI
- Rich CDI ecosystem already evolving
- Tools/utilities, extending Java EE, integration with
Java EE APIs, integrating with non-standard APIs, making Java EE features available in non-Java EE environments
- Arquillian possibly most important CDI extension
- Use portable extensions judiciously
SLIDE 45 CDI ECOSYSTEM SNAPSHOT
Implementations
Weld CanDI OpenWebBeans
Runtimes Portable Extensions Tools
SLIDE 46
CDI PORTABLE EXTENSIONS SNAPSHOT
SLIDE 47
ARQUILLIAN UNIT TEST
SLIDE 48 SUMMARY
- CDI critical part of Java EE – now and going
forward
- CDI well-received by community
- Focus on loose-coupling, Java-centric type-safety,
annotations, expressiveness, fluency and ease-of- use
- Utilize CDI effectively to maximize benefits
- Continuously refactor to patterns
- Have fun!
SLIDE 49 REFERENCES
- JSR 299: Contexts and Dependency Injection for
Java EE, http://jcp.org/en/jsr/detail?id=299
- Weld Reference, http://docs.jboss.org/weld/
reference/1.0.0/en-US/html/
- CDI Advocacy, http://cdisource.org/site/
- Weld, the JBoss reference implementation for JSR
299, http://seamframework.org/Weld
- OpenWebBeans, Apache implementation of JSR
299, http://openwebbeans.apache.org
- CanDI, the JSR 299 implementation for Caucho
Resin, http://caucho.com/projects/candi/
SLIDE 50 REFERENCES
- Seam 3, http://seamframework.org
- Apache MyFaces CODI, http://
myfaces.apache.org/extensions/cdi/
- Arquillian, http://www.jboss.org/arquillian
- Seam Forge, http://seamframework.org/
Documentation/SeamForge