Miles to go …

August 24, 2010

TOTD #144: CDI @Produces for container-managed @Resource

Filed under: General — arungupta @ 4:07 am

Contexts & Dependency Injection (CDI) in Java EE 6 provides type-safe dependency injection. The type-safety part comes from the fact that no String-based identifiers are used for dependency injection. Instead CDI runtime uses the typing information that is already available in the Java object model.

Java EE 5 already had resource injection available in terms of PersistenceContext, PersistenceUnit, Resource, and others. But they require String-based identifiers to identify the resource to be injected. For example:

  • @PersistenceUnit(unitName="SOME_NAME")
  • @Resource(name="JNDI_NAME")
  • @WebServiceRefs(lookup="JNDI_NAME_OF_WEB_SERVICE_REF")

The main proposition of CDI is type-safety. This Tip Of The Day explains how @Produces annotation provided by CDI can be used to centralize all these String-based resource injection and add a facade of type-safety on them. Specifically, it shows how type-safety can be achieved for @PersistenceUnit. A similar approach can be taken for other String-based resource injections as well.

  1. Create a Singleton-scoped bean or Application-scoped bean as:
    import javax.inject.Singleton;
    @Singleton
    public class ApplicationResources {
    }
    

    All the Java EE component environment references can be centralized in this bean.

  2. If the PersistenceUnit is currently initialized as:
    @PersistenceUnit(unitName="StatesPU") EntityManagerFactory statesEMF;
    

    in other Java EE components, such as Servlet, then it can be alternatively defined in the type-safe manner using the following steps:

    1. Define a new Qualifier as:
      import static java.lang.annotation.ElementType.TYPE;
      import static java.lang.annotation.ElementType.FIELD;
      import static java.lang.annotation.ElementType.PARAMETER;
      import static java.lang.annotation.ElementType.METHOD;
      import static java.lang.annotation.RetentionPolicy.RUNTIME;
      import java.lang.annotation.Retention;
      import java.lang.annotation.Target;
      import javax.inject.Qualifier;
      @Qualifier
      @Retention(RUNTIME)
      @Target({METHOD, FIELD, PARAMETER, TYPE})
      public @interface StatesDatabase {
      }
      
    2. Add the type-safe definition of "EntityManagerFactory" in "ApplicationResources" bean (defined above) as:
      @Produces @PersistenceUnit(unitName="StatesPU") @StatesDatabase EntityManagerFactory statesEMF;
      

    3. The "EntityManagerFactory" can now be injected in the Servlet in a type-safe manner as:
      @Inject @StatesDatabase EntityManagerFactory emf;
      

This procedure can be repeated for other String-based resources as well and thus centralize all of them at one place. And now your application becomes more type-safe! With this TOTD, you can use @Inject for injecting your container- and application-managed resources easily.

Read the latest documentation on Weld (Reference Implementation for CDI and included in GlassFish) for more details.

Technorati: totd cdi javaee6 glassfish weld produces typesafety

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #145: CDI Events – a light-weight producer/consumer in Java EE 6
  2. TOTD #109: How to convert a JSF managed bean to JSR 299 bean (Web Beans) ?
  3. TOTD #151: Transactional Interceptors using CDI – Extensible Java EE 6
  4. TOTD #134: Interceptors 1.1 in Java EE 6 – What and How ?
  5. TOTD #129: Managed Beans 1.0 in Java EE 6 – What and How ?

4 Comments »

  1. Hi Arun,

    I tried your approach with @PersistenceContext and EntityManager and it failed.

    Is the TOTD only applicable to @PersistenceUnit? Is there any way to centralised @EntityManager injected in various EJBs?

    Comment by DWuysan — October 4, 2010 @ 3:17 pm

  2. DWusyan,

    Should work for both. What is the exact syntax you are using ?

    Comment by Arun Gupta — October 5, 2010 @ 7:08 am

  3. Hi Arun,

    I finally got it working with @PersistenceContext.

    As far as I can see, there are a number differences between your example and mine actually lies on the use of the producer method.

    Please refer to the post by John Ament <http://seamframework.org/Community/CDISpec351DeclaringAResourceDoesNotSeemToWorkInRI#comment114350>

    So, on the ApplicationResources.java will be as follows:

    @ApplicationScoped
    @Singleton
    public class ApplicationResources {

    @PersistenceContext(unitName = "mck-ejbPU")
    EntityManager em;

    @Produces
    @OnlineDatasource
    public EntityManager produce() { return em; }

    }

    If I use field producer (see below), it does not work:

    @Produces @PersistenceContext(unitName = "mck-ejbPU") @OnlineDatasource EntityManager em;

    Comment by DWuysan — October 5, 2010 @ 3:47 pm

  4. DWuysan, I was able to run the sample without problems and field producer worked for me.

    Arun, I was wondering whether some NetBeans code wizards should utilize field producers but so far I do not see much benefit for user. If type safety is a concern then user could stick with EJBs and would get the same result simpler way, no? For example:

    @javax.ejb.Singleton
    public class ApplicationResources {

    private @PersistenceContext(unitName="StatesPU") EntityManager em;

    public EntityManager getStatesDatabase() {
    return em;
    }
    }

    and in order to use it you inject singleton bean:

    private @EJB ApplicationResources ar;

    and use it:

    ar.getStatesDatabase();

    Or is it a matter of finding more suitable case, for example a unit testing one where you want to inject different persistence context from unit tests?

    Comment by David — October 21, 2010 @ 6:59 am

RSS feed for comments on this post. TrackBack URL

Leave a comment

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress