contexts and dependency injection for the javaee platform

36
CDI – Contexts and CDI – Contexts and Dependency Injection for Dependency Injection for the JavaEE platform the JavaEE platform (JSR299) (JSR299) Bozhidar Bozhanov Bulgarian Association of Software Developer www.devbg.org

Upload: bozhidar-bozhanov

Post on 23-Aug-2014

5.538 views

Category:

Investor Relations


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Contexts and Dependency Injection for the JavaEE platform

CDI – Contexts and CDI – Contexts and Dependency Injection for the Dependency Injection for the JavaEE platform (JSR299)JavaEE platform (JSR299)

Bozhidar BozhanovBulgarian Association of Software Developers

www.devbg.org

Page 2: Contexts and Dependency Injection for the JavaEE platform

About meAbout me

• Senior Java Developer at Fish4• 3+ years experience with Spring and

dependency injection• Implementor of JSR-299 as a university

project• Committer at Hector (Java Cassandra API)• http://techblog.bozho.net

Page 3: Contexts and Dependency Injection for the JavaEE platform

Dependency injection?Dependency injection?

• Classes define what are their dependencies, not how they obtain them

• Object dependencies are set externally• Unit-test and mocking friendly• DI frameworks - objects are managed and

have a lifecycle

Page 4: Contexts and Dependency Injection for the JavaEE platform

HistoryHistory

• Theoretical basis - GoF Hollywood principle; Steffano Mazzocchi

• Spring – 2002/2003, Rod Johnson• Pico Container - 2003• Martin Fowler popularized the term - 2004• JBoss Seam, Google Guice, EJB 3.0• Contexts and Dependency Injection (JSR-

299, JavaEE 6) - 2006-2009

Page 5: Contexts and Dependency Injection for the JavaEE platform

Current problemsCurrent problems

• Problematic integration between JavaEE components

• „Crippled“ dependency-injection in EJB• No standard – only propriatary DI

frameworks (spring, guice, seam)• Extended reliance on string qualifiers (no

compile-time safety)

Page 6: Contexts and Dependency Injection for the JavaEE platform

JSR-299JSR-299

• What's a JSR?• CDI Initially named „Web Beans“• Expert Group formed in June 2006, spec-lead

is Gavin King• Early draft (2007), Public review (2008), Final

draft (mid-2009), Ralease (Dec 2009)• Bob Lee (Guice) left the expert group• IBM voted „No“, Google voted „Yes“,

VMware (SpringSource) and Eclipse didn't vote.

Page 7: Contexts and Dependency Injection for the JavaEE platform

What is CDIWhat is CDI

• Type-safe DI framework (based on Seam, Guice and Spring)

• Uses JSR-330 (Dependency Injection for Java), lead by Rod Johnson (Spring) and Bob Lee (Guice), which defines only DI annotations (for JavaSE)

• DI JavaEE-wide – JSF managed beans, EJB, JavaEE Resources

Page 8: Contexts and Dependency Injection for the JavaEE platform

Implementations; web profileImplementations; web profile

• Three implementations: JBoss Weld, Apache OpenWebBeans and Resin CanDI

• Only one stable at the moment – Weld, used in Glassfish v3 and JBoss AS (5.2, 6)

• JavaEE 6 has the so-called „profiles“. CDI is part of the „Web profile“

• CDI implementations are not limited to application servers (with the help of extensions)

Page 9: Contexts and Dependency Injection for the JavaEE platform

Java EE structure with CDIJava EE structure with CDI

Page 10: Contexts and Dependency Injection for the JavaEE platform

Beans and bean archivesBeans and bean archives

• A bean archive has META-INF/beans.xml• All classes within a bean archive are beans,

and eligible for injection• All classes in outside bean archives are not

beans• Beans can have type(s), scope, EL name,

qualifiers, interceptors.• Beans can be JSF beans, EJBs, JavaEE

resources

Page 11: Contexts and Dependency Injection for the JavaEE platform

• @javax.inject.Inject is used:@javax.inject.Inject is used:

InjectionInjection

publicpublic classclass OrdersBean { OrdersBean {@Inject@Inject privateprivate OrdersDao OrdersDao daodao;;

}}

• The „dao“ field is called „injection point“. The „dao“ field is called „injection point“. Injection point types are:Injection point types are:

• FieldField• ConstructorConstructor• SetterSetter• Initializer Initializer

Page 12: Contexts and Dependency Injection for the JavaEE platform

Injection pointsInjection points

publicpublic classclass OrdersBean { OrdersBean { @Inject@Inject privateprivate OrdersDao OrdersDao daodao;;

@Inject@Inject publicpublic OrdersBean(OrdersDao dao){} OrdersBean(OrdersDao dao){}

@Inject@Inject publicpublic voidvoid init(OrdersDao dao) {} init(OrdersDao dao) {}

@Inject@Inject publicpublic voidvoid setOrdersDao(OrdersDao dao){} setOrdersDao(OrdersDao dao){}}}

Page 13: Contexts and Dependency Injection for the JavaEE platform

• Inject into:Inject into:– POJOsPOJOs– EJB Session BeansEJB Session Beans– ServletsServlets

• Injection candidates:Injection candidates:– POJOsPOJOs– EJB Session BeansEJB Session Beans– JavaEE ResourcesJavaEE Resources

Injection targetsInjection targets

Page 14: Contexts and Dependency Injection for the JavaEE platform

Bean scopesBean scopes

• Built-in scopes (normal vs pseudo):• @ApplicationScoped – i.e. Singleton• @RequestScoped – created on http request• @SessionScoped – within a HttpSession• @ConversationScoped – between request

and session• @Dependent (default, pseudo) – the object

lives as long as the object it is injected into• Custom scopes

Page 15: Contexts and Dependency Injection for the JavaEE platform

• @Named(@Named(""beanNamebeanName"")). Defaults to the . Defaults to the decapitalized, simple name of the classdecapitalized, simple name of the class

• Used in EL expressions:Used in EL expressions:

Bean nameBean name

<<h:outputTexth:outputText valuevalue=="#{orderBean.order.price}""#{orderBean.order.price}" />/>

• Used in injections (discouraged)Used in injections (discouraged)@Inject@Inject @Named@Named(("ordersBean""ordersBean"))privateprivate OrdersBean OrdersBean orderBeanorderBean;;

Page 16: Contexts and Dependency Injection for the JavaEE platform

• Qualifiers are annotations (unlike in spring):Qualifiers are annotations (unlike in spring):

QualifiersQualifiers

@Qualifier //retention & target ommitted@Qualifier //retention & target ommittedpublicpublic @interface@interface SynchronousSynchronous {} {}

• Qualifiers are used to differentiate beans with the same Qualifiers are used to differentiate beans with the same type:type:

@@Inject Inject @@Synchronous Synchronous privateprivate CreditCardProcessor processor; CreditCardProcessor processor;

@@SynchronousSynchronouspublicpublic class class SynchronousCreditCardProcessorSynchronousCreditCardProcessor implementsimplements CreditCardProcessor {..} CreditCardProcessor {..}@@AsynchronousAsynchronouspublicpublic classclass AsyncCreditCardProcessor AsyncCreditCardProcessor implementsimplements CreditCardPRocessor {..} CreditCardPRocessor {..}

Page 17: Contexts and Dependency Injection for the JavaEE platform

• @Any@Any – all beans have this, unless they have – all beans have this, unless they have @New@New• @Default, @Named@Default, @Named• @New @New – – forces the container to return a new bean forces the container to return a new bean instance each timeinstance each time

Built-in qualifiersBuilt-in qualifiers

@@New New publicpublic classclass SomeBean {..} SomeBean {..}

publicpublic classclass AnotherBean { AnotherBean { @@Inject SomeBean bean1;Inject SomeBean bean1; @@Inject SomeBean bean2; Inject SomeBean bean2; @@PostConstruct PostConstruct voidvoid init() { init() { // false// false System.out.println(bean1 == bean2);System.out.println(bean1 == bean2); }}}}

Page 18: Contexts and Dependency Injection for the JavaEE platform

• Stereotypes are used to reduce the amount Stereotypes are used to reduce the amount of boilerplate code:of boilerplate code:

StereotypesStereotypes

@@Stereotype Stereotype //denoting a stereotype//denoting a stereotype@@Named Named // built-in qualifier// built-in qualifier@@RequestScoped RequestScoped // scope// scopepublicpublic @interface@interface RequestScopedSecureBean {}RequestScopedSecureBean {}

@@RequestScopedNamedRequestScopedNamed BeanBeanpublicpublic classclass OrdersBean {..} OrdersBean {..}

Page 19: Contexts and Dependency Injection for the JavaEE platform

DemoDemo(Beans, Injection, Qualifiers, Stereotypes, EL)

Page 20: Contexts and Dependency Injection for the JavaEE platform

• A way to utilize complex constructionA way to utilize complex construction• Allow non-beans to be injected (i.e. 3Allow non-beans to be injected (i.e. 3rdrd party party classes outside a bean-archive)classes outside a bean-archive)• Handles object disposalHandles object disposal

ProducersProducers

//this class is within a bean archive//this class is within a bean archiveclassclass ConnectionProducer { ConnectionProducer { @Produces@Produces Connection createConnection() { Connection createConnection() { // create and return jdbc connection// create and return jdbc connection }} // when the object gets out of scope // when the object gets out of scope voidvoid dispose( dispose(@Disposes@Disposes Connection con) { Connection con) { con.close();con.close(); }}}}

Page 21: Contexts and Dependency Injection for the JavaEE platform

• Allow injecting JavaEE resources:Allow injecting JavaEE resources:

Producer fieldsProducer fields

@@Produces Produces @@SomeTopicSomeTopic@@Resource(name=Resource(name="topics/SomeTopic""topics/SomeTopic"))privateprivate Topic someTopic; Topic someTopic;

@@ProducesProduces@@PersistenceContextPersistenceContextprivateprivate EntityManager entityManager; EntityManager entityManager;

@@Produces Produces // non-JaveEE producer field// non-JaveEE producer fieldprivateprivate Some3rdPartyBean bean = Some3rdPartyBean bean = newnew Some3rdPartyBean(); Some3rdPartyBean();

Page 22: Contexts and Dependency Injection for the JavaEE platform

• Gives information about the injection pointGives information about the injection point

Injection point metadataInjection point metadata

@@Produces Logger createLogger(InjectionPointProduces Logger createLogger(InjectionPoint injectionPoint) { injectionPoint) { returnreturn Logger.getLogger(injectionPoint Logger.getLogger(injectionPoint .getMember().getDeclaringClass()); .getMember().getDeclaringClass()); }}

@Produces@Produces @@HttpParam(HttpParam(""""))String getParamValue(ServletRequest request, String getParamValue(ServletRequest request, InjectionPoint ip) {InjectionPoint ip) { returnreturn request.getParameter(ip request.getParameter(ip .getAnnotation(HttpParam..getAnnotation(HttpParam.class)class).value());.value()); }}}}

Page 23: Contexts and Dependency Injection for the JavaEE platform

• Decorators decorate all interfaces they Decorators decorate all interfaces they implementimplement• @Delegate @Delegate is used to inject the original is used to inject the original objectobject• Decorators must be explicitly listed in Decorators must be explicitly listed in beans.xml, in their respective orderbeans.xml, in their respective order• Decorators can be abstractDecorators can be abstract

DecoratorsDecorators

@@DecoratorDecoratorpublicpublic classclass LogDecorator LogDecorator implementsimplements Logger { Logger { @@Delegate Delegate @@Any Any privateprivate Logger Logger loggerlogger;; @Override@Override publicpublic voidvoid log(String msg) { log(String msg) { loggerlogger.log(timestamp() + .log(timestamp() + ":"":" + msg); + msg); }}}}

Page 24: Contexts and Dependency Injection for the JavaEE platform

• Interceptor bindings (can be nested or included Interceptor bindings (can be nested or included in stereotypes)in stereotypes)

InterceptorsInterceptors

@@InterceptorBinding InterceptorBinding // + retention & target// + retention & targetpublicpublic @interface@interface TransactionalTransactional{}{}

@@InterceptorBindings @TransactionalInterceptorBindings @Transactionalpublicpublic @interface@interface DataAccessDataAccess {} {}

• Declaring the actual interceptor:Declaring the actual interceptor:@@Transactional Transactional @@InterceptorInterceptorpublicpublic classclass TransactionInterceptor { TransactionInterceptor { @@AroundInvokeAroundInvoke publicpublic Object manage(InvocationContext ctx) Object manage(InvocationContext ctx) throwsthrows Exception { .. } Exception { .. }}}

Page 25: Contexts and Dependency Injection for the JavaEE platform

• Declaring the interceptor on the target beanDeclaring the interceptor on the target bean

Interceptors (2)Interceptors (2)

@@Transactional Transactional //all methods are transactional//all methods are transactionalpublic classpublic class OrderService { .. } OrderService { .. }

• Like decorators, must be enabled in beans.xmlLike decorators, must be enabled in beans.xml• Interceptors-to-intercepted targets: many-to-Interceptors-to-intercepted targets: many-to-manymany• Interceptors-to-interceptor bindings: many-to-Interceptors-to-interceptor bindings: many-to-manymany• Binding vs Binding vs @NonBinding@NonBinding interceptor attributes interceptor attributes

Page 26: Contexts and Dependency Injection for the JavaEE platform

DemoDemo(Producers, Decorators, Interceptors)

Page 27: Contexts and Dependency Injection for the JavaEE platform

Programmatic lookupProgrammatic lookup

@@Inject Inject @@AnyAnyprivateprivate Instance<CreditCardProcessor> ccProc; Instance<CreditCardProcessor> ccProc;public voidpublic void processPayment( processPayment( Payment payment, Payment payment, booleanboolean synchronously) { synchronously) { Annotation qualifier = synchronouslyAnnotation qualifier = synchronously ? ? newnew SynchronousLiteral() SynchronousLiteral() : : newnew AsynchronousLiteral(); AsynchronousLiteral(); CreditCardProcessor actualProcessor =CreditCardProcessor actualProcessor = ccProc.select(qualifier).get();ccProc.select(qualifier).get(); actualProcessor.process(payment);actualProcessor.process(payment);}}

classclass SynchronousLiteral SynchronousLiteral extendsextends AnnotationLiteral<Synchronous> {}AnnotationLiteral<Synchronous> {}

• When qualifiers are to be examined at When qualifiers are to be examined at runtime:runtime:

Page 28: Contexts and Dependency Injection for the JavaEE platform

EventsEvents

@@Inject Inject @@EventQualifierEventQualifierprivateprivate Event<SampleEvent> event; Event<SampleEvent> event;

publicpublic voidvoid fireEvent() { fireEvent() { event.fire(new SimpleEvent());event.fire(new SimpleEvent());}}

• Event observer (with the appropriate qualifier)Event observer (with the appropriate qualifier)

publicpublic voidvoid observes( observes( @@Observes Observes @@EventQualifierEventQualifier SampleEvent event) { .. }SampleEvent event) { .. }}}

• Event producer, making use of generics:Event producer, making use of generics:

Page 29: Contexts and Dependency Injection for the JavaEE platform

Events (2)Events (2)

@@Inject Inject @@Any Event<LoggedEvent> loggedEvent;Any Event<LoggedEvent> loggedEvent;publicpublic voidvoid login(user) { login(user) { LoggedEvent event = LoggedEvent event = new new LoggedEvent(user);LoggedEvent(user); ifif (user.isAdmin()) { (user.isAdmin()) { loggedEvent.select(loggedEvent.select( newnew AdminLiteral()).fire(event); AdminLiteral()).fire(event); } } elseelse { { loggedEvent.fire(event);loggedEvent.fire(event); }}}}

• Dynamic choice of qualifiersDynamic choice of qualifiers

• @Observes(notifyObserver=IF_EXISTS)@Observes(notifyObserver=IF_EXISTS)notifies only if an instance of the declaring notifies only if an instance of the declaring bean bean exists in the current contextexists in the current context

Page 30: Contexts and Dependency Injection for the JavaEE platform

Circular dependenciesCircular dependencies

@@ApplicationScopedApplicationScopedpublicpublic classclass Bean1 { Bean1 { @@InjectInject publicpublic Bean1(Bean2 bean2) {..} Bean1(Bean2 bean2) {..}}}

@@ApplicationScopedApplicationScopedpublicpublic classclass Bean2 { Bean2 { @@InjectInject publicpublic Bean2(Bean1 bean1) {..} Bean2(Bean1 bean1) {..}}}

• CDI implementations must use proxies for all CDI implementations must use proxies for all scopes, except scopes, except @Dependent@Dependent

Page 31: Contexts and Dependency Injection for the JavaEE platform

DemoDemo(Programatic lookup, Events, Circular Dependencies)

Page 32: Contexts and Dependency Injection for the JavaEE platform

Portable extensionsPortable extensions• CDI allows plugable extensions that can

access the context, hook to context events• Providing its own beans, interceptors and

decorators to the container• Injecting dependencies into its own objects

using the dependency injection service• Providing a context implementation for a

custom scope• Augmenting or overriding the annotation-

based metadata with metadata from some other source

Page 33: Contexts and Dependency Injection for the JavaEE platform

Portable extensions (2)Portable extensions (2)• http://seamframework.org/Weld/

PortableExtensionsPackage• XML configuration• Wicket integration• JavaSE and Servlet container support

Page 34: Contexts and Dependency Injection for the JavaEE platform

ConcernsConcerns• Lack of standardized XML configuration• Not many „extras“ available yet• Annotation mess• CDI interceptors might not be sufficient,

compared to Spring AOP (AspectJ syntax)• (un)portable extensions may become exactly

what spring is being critized for – size and complexity

• Complex• Being a standard?

Page 35: Contexts and Dependency Injection for the JavaEE platform

• http://seamframework.org/service/File/105766• http://www.slideshare.net/johaneltes/java-ee6-cd

i• http://www.slideshare.net/mojavelinux/jsr299-cdi-

weld-the-future-of-seam-javaone-2010• http://download.oracle.com/javaee/6/tutorial/doc/

gjbnz.html

ResourcesResources

Page 36: Contexts and Dependency Injection for the JavaEE platform

QuestionsQuestions??