Thursday Oct 03, 2013

Default CDI Enablement in Java EE 7

As you may already know, in Java EE 6, you needed to explicitly add a beans.xml file in your application archive in order for CDI scanning to work. Because DI is correctly considered such a pervasive concern, Java EE developers often found this requirement confusing. In my personal experience, eight times out of ten when someone asked me "why CDI is not working", it was because they had not added beans.xml in their application.

One of the most significant changes in CD 1.1/Java EE 7 is that by popular request, CDI is now enabled by default. This means that there's no need to explicitly add a beans.xml to enable DI any more. However, it is also very important to understand that CDI now also provides finer grained control over component scanning via the 'bean-discovery-mode' attribute. This attribute has three possible values:

  • 'annotated' - loosely translated, means that only components with a class-level annotation are processed.
  • 'all' - all components are processed, just like they were in Java EE 6 with the explicit beans.xml.
  • 'none' - CDI is effectively disabled.

By default, if you specify nothing and there is no beans.xml, the bean discovery mode of 'annotated' and not 'all' is assumed. This is probably fine for the vast majority of real world applications. However, if you are in fact using beans without class level annotations (which I sometimes do when it makes sense), you'll need to explicitly enable 'all' in a beans.xml like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
       http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
</beans>

As you can imagine, bean-discovery-mode='none' comes in very handy if you have another DI system that uses JSR 330 annotations such as Guice or Spring. In GlassFish 4, you also have the option of turning off implicit CDI scanning if you want. You can do this using the new 'implicitCdiEnabled' property like so:

asadmin deploy --property implicitCdiEnabled=false <archive>

Beyond the bean discovery mode, CDI 1.1 comes with other finer grained controls over scanning as well which you should explore via the fairly readable official specification itself.