Miles to go …

April 25, 2011

TOTD #161: Java EE 6 CDI Qualifiers explained – @Default, @Any, @New, @Named

Filed under: General — arungupta @ 1:00 am

The CDI specification (JSR-299) defines "Qualifer" as a means to uniquely identify one of the multiple implementations of the bean type to be injected. The spec defines certain built-in qualifiers (@Default, @Any, @Named, @New) and new qualifiers can be easily defined as well. This Tip Of The Day (TOTD) discusses the in-built qualifiers and how they can be used.

The @Named qualifier makes a bean EL-injectable, that’s it!

The @Default qualifier, appropriately called as "default qualifier", exists on all beans without an explicit qualifer, except @Named. Consider the following bean type and implementation:

public interface Greeting {
    public String greet(String name);
}
public class SimpleGreeting implements Greeting {
    public String greet(String name) {
        return "Hello " + name;
    }
}

So SimpleGreeting defined above is equivalent to:

@Default
public class SimpleGreeting implements Greeting {
    . . .
}

Similarly

@Named
public class SimpleGreeting implements Greeting {
    . . .
}

is equivalent to:

@Named
@Default
public class SimpleGreeting implements Greeting {
    . . .
}

The default qualifier works for the type injection as well. So

@Inject Greeting greeting;

and

@Inject @Default Greeting greeting;

are equivalent. However it is not recommended to use @Named as injection point qualifier, except in the case of integration with legacy code that uses string-based names to identify beans.

@Any is another in-built qualifier on all beans, including the ones with implicit or explicit @Default qualifier, except @New qualified beans (more on this later). So the SimpleGreeting implementation is equivalent to:

@Default @Any
public class SimpleGreeting implements Greeting {
    . . .
}

And can be injected as:

@Inject @Any Greeting greeting;

or even

@Inject @Any @Default Greeting greeting;

Now lets add a new implementation of the Greeting as:

public class FancyGreeting implements Greeting {
    public String greet(String name) {
        return "Nice to meet you, hello " + name;
    }
}

Now all of the following injections fail:

@Inject Greeting greeting;
@Inject @Default Greeting greeting;
@Inject @Any Greeting greeting;
@Inject @Default @Any Greeting greeting;

with the "ambiguous dependencies" error because both the implementations now have @Default and @Any qualifiers.

This can be resolved by adding a new qualifier called @Fancy to the FancyGreeting implementation as:

@Fancy
public class FancyGreeting implements Greeting {
    . . .
}

which is also equivalent to:

@Fancy @Any
public class FancyGreeting implements Greeting {
    . . .
}

Now all the following inject statements:

@Inject Greeting greeting;
@Inject @Default Greeting greeting;
@Inject @Any @Default Greeting greeting;

will inject the SimpleGreeting implementation. However

@Inject @Any Greeting greeting;

will throw an "ambiguous dependency" error because now there are two implementations with that qualifier. The right implementation can be picked by specifying the additional qualifier such as:

@Inject @Any @Default Greeting greeting;

will inject the SimpleGreeting implementation and

@Inject @Any @Fancy Greeting greeting;

will inject the FancyGreeting implementation. The following injection will work anyway:

@Inject @Fancy Greeting greeting;

Lastly

@Inject @Default @Fancy Greeting greeting;

will give an "unsatisfied dependency" error because any bean with an explicit qualifier, except @Named, does not have the @Default qualifier.

@Any may also be used to add qualifiers programmatically such as:

@Inject @Any Instance<Greeting> greeting;
greeting.select(new AnnotationLiteral<Fancy>(){}).get();

will return a Greeting implementation with @Fancy qualifier. Here the "javax.enterprise.inject.Instance" and "javax.enteprise.util.AnnotationLiteral" classes are defined by the CDI spec.

@Any may also be used to iterate over all Greeting implementations such as:

@Inject @Any Instance<Greeting> greeting;
for (Greeting g : greeting) {
    // do something with g
}

The @New qualifier allows to obtain a depdendent object of a specified class, independent of the declared scope. So if SimpleGreeting is defined as:

@RequestScoped
public class SimpleGreeting implements Greeting {
    . . .
}

and injected as:

@Inject Greeting greeting;

then a request-scoped Greeting implementation (SimpleGreeting in this case) is injected. However if it is injected as:

@Inject @New Greeting greeting;

then the injected SimpleGreeting is in the @Dependent scope and only has @New qualifier (neither @Default or @Any).

I tried all of this using GlassFish 3.1 and NetBeans 7.0 that provides complete development and fully-clustered deployment environment for your Java EE 6 applications. Where are you deploying your Java EE 6 apps ?

Technorati: totd cdi qualifier javaee6 glassfish

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #129: Managed Beans 1.0 in Java EE 6 – What and How ?
  2. TOTD #145: CDI Events – a light-weight producer/consumer in Java EE 6
  3. TOTD #144: CDI @Produces for container-managed @Resource
  4. TOTD #134: Interceptors 1.1 in Java EE 6 – What and How ?
  5. TOTD #124: OSGi Declarative Services in GlassFish – Accessed from a Java EE client

3 Comments »

  1. Have you purposefully missed showing how to create a new Qualifier for @Fancy or is it not needed?

    Comment by Sreekanth — April 25, 2011 @ 5:30 am

  2. Sreekanth,

    That is pretty straight forward and boiler-plate code so left it out. Moreover NetBeans let you generate it with a single click anyway :-)

    Comment by Arun Gupta — April 25, 2011 @ 6:07 am

  3. blog.arungupta.me : strip and piss in the grass vladlenaivfun.blogspot.com/2012/02/strip-and-piss-in-the-grass.html

    Comment by PaydayIdiobia — March 30, 2012 @ 11:25 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