{"id":3849,"date":"2012-02-22T12:50:09","date_gmt":"2012-02-22T17:50:09","guid":{"rendered":"http:\/\/jianmingli.com\/wp\/?p=3849"},"modified":"2012-06-16T08:10:13","modified_gmt":"2012-06-16T13:10:13","slug":"cdi-context-and-dependency-injection-jsr-299","status":"publish","type":"post","link":"https:\/\/jianmingli.com\/wp\/?p=3849","title":{"rendered":"CDI: Context and Dependency Injection (JSR-299)"},"content":{"rendered":"<div class='toc wptoc'>\n<h2>Contents<\/h2>\n<ol class='toc-odd level-1'>\n\t<li>\n\t\t<a href=\"#Introduction\">Introduction<\/a>\n\t\t<ol class='toc-even level-2'>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Fundamental_Services\">Fundamental Services<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Other_Services\">Other Services<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Loose_Coupling\">Loose Coupling<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Strong_Typing_Benefits\">Strong Typing Benefits<\/a>\n\t\t\t<\/li>\n\t\t<\/ol>\n\t<li>\n\t\t<a href=\"#CDI_Beans\">CDI Beans<\/a>\n\t\t<ol class='toc-even level-2'>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Bean_Attributes\">Bean Attributes<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#What_is_a_Managed_Bean\">What is a Managed Bean<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Injectable_Objects\">Injectable Objects<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Alternatives\">Alternatives<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Interceptors\">Interceptors<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Using_Qualifiers\">Using Qualifiers<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Using_Qualifier_with_Members\">Using Qualifier with Members<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Injecting_Beans\">Injecting Beans<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Using_Scopes\">Using Scopes<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Producer_Methods\">Producer Methods<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#Obtain_Bean_Programmatically\">Obtain Bean Programmatically<\/a>\n\t\t\t<\/li>\n\t\t\t<li>\n\t\t\t\t<a href=\"#InjectionPoint_object\">InjectionPoint object<\/a>\n\t\t\t<\/li>\n\t\t<\/ol>\n\t<li>\n\t\t<a href=\"#Configure_CDI_App\">Configure CDI App<\/a>\n\t<\/li>\n\t<li>\n\t\t<a href=\"#References\">References<\/a>\n\t<\/li>\n<\/ol>\n<\/ol>\n<\/div>\n<div class='wptoc-end'>&nbsp;<\/div>\n<span id=\"Introduction\"><h2>Introduction<\/h2><\/span>\n<span id=\"Fundamental_Services\"><h3>Fundamental Services<\/h3><\/span>\n<p>* Contexts<br \/>\n&#8211; Bind stateful components to lifecycle contexts (i.e. client does not control bean&#8217;s lifecycle, container does)<br \/>\n&#8211; Lifecycle contexts are well defined and extensible<br \/>\n* Dependency injection<br \/>\n&#8211; Inject components into an application in a <strong>typesafe<\/strong> way<br \/>\n&#8211; Deployment time decision on which implementation of a particular interface to inject<\/p>\n<span id=\"Other_Services\"><h3>Other Services<\/h3><\/span>\n<p>* EL (expression language) integration:<br \/>\n&#8211; Components can be used directly on JSP\/JSF pages<br \/>\n* Decorate injected components<br \/>\n* Associate interceptors with components using typesafe interceptor bindings<br \/>\n* Event notification model<br \/>\n* Added web conversation scope (in addition to request, session, and application)<br \/>\n* Complete SPI spec:<br \/>\n&#8211; Clean third party integration<\/p>\n<span id=\"Loose_Coupling\"><h3>Loose Coupling<\/h3><\/span>\n<p>* Server\/client decoupling via<br \/>\n&#8211; Well-defined types and qualifiers (so that server implementation may vary)<br \/>\n* Component lifecycle decoupling via<br \/>\n&#8211; Adding context to components<br \/>\n&#8211; Automatic life cycle management for components<br \/>\n&#8211; Allowing stateful components to interact like services (purely by message passing)<br \/>\n* Message producer\/consumer decoupling via events<br \/>\n* Orthogonal concerns decoupling via JEE interceptors<\/p>\n<span id=\"Strong_Typing_Benefits\"><h3>Strong Typing Benefits<\/h3><\/span>\n<p>* No lookups using string-based names for wiring and correlations (errors can be detected at compile time)<br \/>\n* Allow Java annotation<\/p>\n<span id=\"CDI_Beans\"><h2>CDI Beans<\/h2><\/span>\n<p>* Beans are stateful whose lifecycles are managed by containers, not by bean clients.<\/p>\n<span id=\"Bean_Attributes\"><h3>Bean Attributes<\/h3><\/span>\n<p>* Bean Types<br \/>\n&#8211; Almost any Java type may be a bean type<br \/>\n* Qualifiers<br \/>\n* Scope<br \/>\n* EL name<br \/>\n* Interceptor bindings<br \/>\n* Implementation<\/p>\n<span id=\"What_is_a_Managed_Bean\"><h3>What is a Managed Bean<\/h3><\/span>\n<p>A managed bean is a top-level Java class if<br \/>\n* Defined to be a managed bean by, for example, JSF spec.<br \/>\n* Or meets all the following conditions:<br \/>\n&#8211; It is not a nonstatic inner class<br \/>\n&#8211; It is a concrete class or is annotated @Decorator<br \/>\n&#8211; It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml<br \/>\n&#8211; It has an appropriate constructor:<br \/>\n1) a constructor with no parameters<br \/>\n2) a constructor annotated @Inject<\/p>\n<span id=\"Injectable_Objects\"><h3>Injectable Objects<\/h3><\/span>\n<p>* Any Java class (almost: what&#8217;s not?)<br \/>\n* Session Beans<br \/>\n* JEE resources: data sources, JMS topics\/queues\/connection factories<br \/>\n* Persistence contexts (JPA EntityManager objects)<br \/>\n* Producer fields<br \/>\n* Objects returned by producer methods<br \/>\n* Web service references<br \/>\n* Remote EJB references<\/p>\n<span id=\"Alternatives\"><h3>Alternatives<\/h3><\/span>\n<p>* Annotate a bean implementation as Alternative<\/p>\n<pre lang=\"java\">\r\npublic @Alternative\r\nclass MockPaymentProcessor extends PaymentProcessorImpl { ... }\r\n<\/pre>\n<p>* Specify to use alternative implementation in beans.xml<\/p>\n<pre lang=\"xml\">\r\n<beans\r\n   xmlns=\"http:\/\/java.sun.com\/xml\/ns\/javaee\"\r\n   xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n   xsi:schemaLocation=\"\r\n      http:\/\/java.sun.com\/xml\/ns\/javaee\r\n      http:\/\/java.sun.com\/xml\/ns\/javaee\/beans_1_0.xsd\">\r\n\r\n   <alternatives>\r\n         <class>org.mycompany.mock.MockPaymentProcessor<\/class>\r\n   <\/alternatives>\r\n\r\n<\/beans>\r\n<\/pre>\n<span id=\"Interceptors\"><h3>Interceptors<\/h3><\/span>\n<p>* An interceptor binding type is a user-defined annotation that is itself annotated <strong>@InterceptorBinding<\/strong>.<br \/>\n* It lets us bind interceptor classes to bean classes with <strong>no <\/strong>direct dependency between the two classes.<br \/>\n* Interceptors are disabled by default. Use beans.xml to enable interceptor and order interceptors.<br \/>\n* Define an interceptor binding type:<\/p>\n<pre lang=\"java\">\r\n@InterceptorBinding\r\n@Inherited\r\n@Target( { TYPE, METHOD })\r\n@Retention(RUNTIME)\r\npublic @interface Transactional {}\r\n<\/pre>\n<p>* Implement the interceptor binding type:<\/p>\n<pre lang=\"java\">\r\npublic @Transactional @Interceptor\r\nclass TransactionInterceptor { ... }\r\n<\/pre>\n<p>* Apply the interceptor to a bean:<\/p>\n<pre lang=\"java\">\r\npublic @SessionScoped @Transactional\r\nclass ShoppingCart implements Serializable { ... }\r\n<\/pre>\n<span id=\"Using_Qualifiers\"><h3>Using Qualifiers<\/h3><\/span>\n<p>* A qualifier is an annotation that you apply to a bean<br \/>\n* A qualifier type is a Java annotation defined as<br \/>\n@Target({METHOD, FIELD, PARAMETER, TYPE})<br \/>\n@Retention(RUNTIME)<br \/>\n* Used to provide various implementations of a particular bean type.<br \/>\n* All non qualifier annotated class are automatically annotated with @Default<br \/>\n* Example:<\/p>\n<pre lang=\"java\">\r\npackage greetings;\r\nimport static java.lang.annotation.ElementType.*;\r\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\r\n\r\nimport java.lang.annotation.*;\r\nimport javax.inject.Qualifier;\r\n\r\n@Qualifier\r\n@Retention(RUNTIME)\r\n@Target({TYPE, METHOD, FIELD, PARAMETER})\r\npublic @interface Informal {}\r\n<\/pre>\n<p>* Use the new Qualifier:<\/p>\n<pre lang=\"java\">\r\npackage greetings;\r\n@Informal\r\npublic class InformalGreeting extends Greeting {\r\npublic String greet(String name) {\r\nreturn \"Hi, \" + name + \"!\";\r\n}\r\n}\r\n<\/pre>\n<span id=\"Using_Qualifier_with_Members\"><h3>Using Qualifier with Members<\/h3><\/span>\n<p>* Define a qualifier with member, e.g. <strong>TestUser <\/strong>:<\/p>\n<pre lang=\"java\">\r\n@Qualifier\r\n@Retention(RUNTIME)\r\n@Target({ TYPE, METHOD, FIELD, PARAMETER })\r\npublic @interface TestUser {\r\n\tUserId userId() default UserId.user1;\t\r\n}\r\n<\/pre>\n<p>* Use <strong>UserId<\/strong> enum class to define available user ids:<\/p>\n<pre lang=\"java\">\r\npublic enum UserId {\r\n\tuser1,\r\n\tuser2;\r\n}\r\n<\/pre>\n<p>* User Provider class to produce test <em>User<\/em> instances:<\/p>\n<pre lang=\"java\">\r\npublic class TestUserProvider {\r\n\r\n\t@Produces @TestUser(userId=UserId.user1)\r\n\tpublic User getUser1(){\r\n                User user = new User(\"user1\");\r\n                return user;\r\n        }\r\n\r\n\t@Produces @TestUser(userId=UserId.user2)\r\n\tpublic User getUser1(){\r\n                User user = new User(\"user2\");\r\n                return user;\r\n        }\r\n<\/pre>\n<p>* Inject <me>User<\/me> instance in classes:<\/p>\n<pre lang=\"java\">\r\n\t@Inject\r\n\t@TestUser(userId = UserId.user1)\r\n\tUser user;\r\n<\/pre>\n<span id=\"Injecting_Beans\"><h3>Injecting Beans<\/h3><\/span>\n<p>* Inject a @Default Greeting object:<\/p>\n<pre lang=\"java\">\r\nimport javax.inject.Inject; \r\npublic class Printer { \r\n  @Inject Greeting greeting; \r\n  ...\r\n}\r\n<\/pre>\n<p>* Inject a @Informal Greeting object:<\/p>\n<pre lang=\"java\">\r\nimport javax.inject.Inject; \r\npublic class Printer { \r\n  @Inject @Informal Greeting greeting; \r\n  ...\r\n}\r\n<\/pre>\n<span id=\"Using_Scopes\"><h3>Using Scopes<\/h3><\/span>\n<p>* CDI introduces two additional scopes, i.e. Dependent and Conversion:<\/p>\n<pre lang=\"java\">\r\n@RequestScoped\r\n@SessionScoped\r\n@ApplicationScoped\r\n@Dependent\r\n@ConversationScoped\r\n<\/pre>\n<p>* Example:<\/p>\n<pre lang=\"java\">\r\nimport javax.inject.Inject; \r\nimport javax.enterprise.context.RequestScoped;\r\nimport javax.inject.Named;\r\n\r\n@Named(\"printer\")\r\n@RequestScoped\r\npublic class Printer { \r\n  @Inject @Informal Greeting greeting; \r\n  ...\r\n}\r\n<\/pre>\n<span id=\"Producer_Methods\"><h3>Producer Methods<\/h3><\/span>\n<p>* Producer methods provide a way to <strong>inject <\/strong>objects that<br \/>\n&#8211; are not beans (e.g. a number)<br \/>\n&#8211; whose values may vary at runtime<br \/>\n&#8211; that require custom initialization (let application take full control of bean instantiation process)<br \/>\n* Example:<br \/>\n&#8211; Define producer method:<\/p>\n<pre lang=\"java\">\r\nprivate int maxNumber = 100;\r\n...\r\n@Produces @MaxNumber int getMaxNumber() {\r\n  return maxNumber;\r\n}\r\n<\/pre>\n<p>&#8211; Inject in another managed bean will initialize maxNumber to 100:<\/p>\n<pre lang=\"java\">\r\n@Inject @MaxNumber private int maxNumber;\r\n<\/pre>\n<span id=\"Obtain_Bean_Programmatically\"><h3>Obtain Bean Programmatically<\/h3><\/span>\n<p>* Get a bean factory:<\/p>\n<pre lang=\"xml\">\r\n@Inject Instance<PaymentProcessor> paymentProcessorSource;\r\n<\/pre>\n<p>* Get a bean factory using qualifier:<\/p>\n<pre lang=\"xml\">\r\n@Inject @Asynchronous Instance<PaymentProcessor> paymentProcessorSource;\r\n<\/pre>\n<p>* Get the bean<\/p>\n<pre lang=\"xml\">\r\nPaymentProcessor p = paymentProcessorSource.get();\r\n<\/pre>\n<span id=\"InjectionPoint_object\"><h3>InjectionPoint object<\/h3><\/span>\n<p>* Used to access metadata relating to the injection point to which it belongs<br \/>\n* Example<br \/>\n&#8211; Declare a LogFactory class to produce a Logger object with appropriate class name:<\/p>\n<pre lang=\"xml\">\r\npublic class LogFactory implements Serializable {\r\n\r\n\tprivate static final long serialVersionUID = 5266112323136335431L;\r\n\r\n\t@Produces\r\n\tLogger createLogger(InjectionPoint injectionPoint) {\r\n\t\tString name = injectionPoint.getMember().getDeclaringClass()\r\n\t\t\t\t.getName();\r\n\t\tLogger log = Logger.getLogger(name);\r\n\r\n\t\treturn log;\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>&#8211; Use following in code to automatically obtain class name:<\/p>\n<pre lang=\"xml\">\r\n@Inject Logger log;\r\n<\/pre>\n<p>&#8211; Above is equivalent to:<\/p>\n<pre lang=\"xml\">\r\nLogger log = Logger.getLogger(MyClass.class.getName());\r\n<\/pre>\n<p>&#8211; For example,<\/p>\n<pre lang=\"java\">\r\nimport mil.osd.dmdc.diss.test.util.WeldJUnit4Runner;\r\n\r\nimport org.apache.log4j.Logger;\r\nimport org.junit.Test;\r\nimport org.junit.runner.RunWith;\r\n\r\n@RunWith(WeldJUnit4Runner.class)\r\npublic class TestLogger {\r\n\t@Inject\r\n\tLogger log;\r\n\t\r\n         \/\/ Note that TestLogger2 has to be injected.\r\n         \/\/ In another word this won't work: TestLogger2 l2 = new TestLogger2(); l2.testLog(); \r\n\t@Inject\r\n\tTestLogger2 l2;\r\n\t\r\n\t@Test\r\n\tpublic void testLogger() {\r\n\t\tlog.debug(\"Test logger...\");\r\n\t}\r\n\t\r\n\t@Test\r\n\tpublic void testLogger2() {\r\n\t\tl2.testLog();\r\n\t}\r\n}\r\n<\/pre>\n<pre lang=\"java\">\r\nimport javax.inject.Inject;\r\nimport org.apache.log4j.Logger;\r\n\r\npublic class TestLogger2 {\r\n\t@Inject\tLogger log;\r\n\r\n\tpublic void testLog(){\r\n\t\tlog.debug(\"TestLogger2...\");\r\n\t}\r\n}\r\n<\/pre>\n<span id=\"Configure_CDI_App\"><h2>Configure CDI App<\/h2><\/span>\n<p>* Must have <em>beans.xml<\/em> in<br \/>\n&#8211; META-INF (EJB modules or JAR files)<br \/>\n&#8211; or WEB-INF (web app): avoid this.<br \/>\n&#8211; or WEB-INF\/classes\/META-INF (web app)<\/p>\n<span id=\"References\"><h2>References<\/h2><\/span>\n<p>* The Java EE 6 Tutorial: Basic Concepts, Fourth Edition By: Eric Jendrock et al Chapter 17<br \/>\n* <a href=\"http:\/\/docs.jboss.org\/weld\/reference\/1.0.0\/en-US\/html\/\">Weld &#8211; JSR-299 Reference Implementation<\/a><br \/>\n* <a href=\"http:\/\/agoncal.wordpress.com\/2011\/05\/23\/to-inject-or-not-to-inject-cdi-is-the-question\/\">To inject or not to inject: CDI is the question<\/a><br \/>\n* <a href=\"http:\/\/code.google.com\/p\/jee6-cdi\/wiki\/DependencyInjectionAnIntroductoryTutorial_Part1\">Dependency Injection &#8211; An Introductory Tutorial &#8211; Part 1<\/a> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Fundamental Services * Contexts &#8211; Bind stateful components to lifecycle contexts (i.e. client does not control bean&#8217;s lifecycle, container does) &#8211; Lifecycle contexts are well defined and extensible * Dependency injection &#8211; Inject components into an application in a &hellip; <a href=\"https:\/\/jianmingli.com\/wp\/?p=3849\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[120],"tags":[],"class_list":["post-3849","post","type-post","status-publish","format-standard","hentry","category-jsf"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8cRUO-105","_links":{"self":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/3849","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3849"}],"version-history":[{"count":18,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/3849\/revisions"}],"predecessor-version":[{"id":4371,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/3849\/revisions\/4371"}],"wp:attachment":[{"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3849"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3849"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jianmingli.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3849"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}