2010-07-11

CDI + JSF 2.0. Part 1

In my previous post I complained about the standard JSF dependency injection mechanism. Therefore I decided it was the right time to look at...

CDI - Contexts and Dependency Injection (JSR 299)


It might be a good idea to read the JSR 299 document (the evaluation version is for you; the other one is for JSR implementers like Guice or Spring) if you haven’t yet.

CDI (formerly known as Web Beans) differs from DI in that it introduces the concept of Context. So you can inject dependencies according to the context too. What contexts are there?
  • Application
  • Request
  • Session
  • Conversation
  • custom

That allows you to have a very flexible dependency injection mechanism where a new object is created by the container and injected whenever it does not exist in your context (or in broader context).


No more @ManagedBean


That’s right. This is how your JSF managed bean will look like now:

package me.m1key.jsf;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

// ...

@Named
@RequestScoped
public class DogsBean {   

In fact, we wouldn’t have to use the @Named annotation to make it a managed bean, because according to the specification (consult JSR) most Java classes are managed beans (i.e. you can use dependency injection in them or inject them). We need @Named, however, to reference that bean from JSF. You can specify another name (the default one is dogsBean in this case).


Accessing a managed bean from JSF


It’s simple.
<h:form>

<h:inputText value="#{dogsBean.name}" />

<h:commandButton value="Send" action="#{dogsBean.send}" />
</h:form>
And that’s it. Our bean is request scoped (CAUTION: make sure you import @RequestScoped from the correct package! That is javax.enterprise.context and not javax.faces.bean) so there will be a new instance of it per request.

Let’s take a look at...

Dependency injection


Let’s create a DAO.

package me.m1key.jsf.dao;

// ...

public interface DogsDao {

 public List<Dog> retrieveAllDogs();

}

package me.m1key.jsf.dao;

import javax.enterprise.context.ApplicationScoped;
// ...

@ApplicationScoped
public class DogsDaoImpl implements DogsDao {

 public DogsDaoImpl() {
     System.out.println(" DogsDaoImpl created: " + this);
 }

 public List<Dog> retrieveAllDogs() {
     List<Dog> dogs = new ArrayList<Dog>();

     Dog dog1 = new Dog();
     dog1.setId(1L);
     dog1.setName("Sega");
     dogs.add(dog1);

     Dog dog2 = new Dog();
     dog2.setId(2L);
     dog2.setName("Fluffy");
     dogs.add(dog2);

     return dogs;
 }

}

Great! This bean is Application scoped, so there is going to be one instance of it per application. Note: the constructor will be called twice, actually. One for the actual object, one for the proxy. Read more about this behavior or consult JSR 299, Section 5.4.

Now, let’s inject it.

 @Inject
 private DogsDao dogsDao;

That’s it. You ask for an interface injection. The container sees there is only one implementation, and injects it. But what if you want to have two implementations of DogsDao?

package me.m1key.jsf.dao;

import javax.enterprise.context.ApplicationScoped;

// ...

@ApplicationScoped    
public class DogsDaoMockImpl implements DogsDao {

With the current configuration, you’d get an exception - the container would not be able to decide which one to instantiate for you. How can you further specify which implementation you need? You should use...

Qualifiers


Qualifiers are a CDI concept that allows you to have more sophisticated criteria for selecting the implementation. Let’s create two qualifiers.

package me.m1key.jsf.qualifiers;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
     ElementType.TYPE })
public @interface Actual {}

package me.m1key.jsf.qualifiers;

// ...

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
     ElementType.TYPE })
public @interface Mock {}

Qualifiers must be annotated with @Qualifier.

Now, let’s annotate the classes.

// ...
import me.m1key.jsf.qualifiers.Actual;

@Actual
@ApplicationScoped
public class DogsDaoImpl implements DogsDao {

// ...
import me.m1key.jsf.qualifiers.Mock;

@Mock
@ApplicationScoped
public class DogsDaoMockImpl implements DogsDao {

Now, when we inject, we must specify which implementation we want, with the same qualifier.

@Inject
@Actual
private DogsDao dogsDao;

And now it works.


Summary


I explained how to use basic CDI which is a new feature of JEE6. Remember that this is a JSF example, so I assumed you run it on an application server. However, CDI itself can be run without a server, so long as you provide an implementation for it (like Weld; the situation is similar to JPA).

Download source code for this article

Next article


In the next article I will explain why and how you can use the @Produces annotation and how to use alternatives (alternatives in the CDI sense).

1 comment:

  1. The development of artificial intelligence (AI) has propelled more programming architects, information scientists, and different experts to investigate the plausibility of a vocation in machine learning. Notwithstanding, a few newcomers will in general spotlight a lot on hypothesis and insufficient on commonsense application. machine learning projects for final year In case you will succeed, you have to begin building machine learning projects in the near future.

    Projects assist you with improving your applied ML skills rapidly while allowing you to investigate an intriguing point. Furthermore, you can include projects into your portfolio, making it simpler to get a vocation, discover cool profession openings, and Final Year Project Centers in Chennai even arrange a more significant compensation.

    Data analytics is the study of dissecting crude data so as to make decisions about that data. Data analytics advances and procedures are generally utilized in business ventures to empower associations to settle on progressively Python Training in Chennai educated business choices. In the present worldwide commercial center, it isn't sufficient to assemble data and do the math; you should realize how to apply that data to genuine situations such that will affect conduct. In the program you will initially gain proficiency with the specialized skills, including R and Python dialects most usually utilized in data analytics programming and usage; Python Training in Chennai at that point center around the commonsense application, in view of genuine business issues in a scope of industry segments, for example, wellbeing, promoting and account.

    The Nodejs Projects Angular Training covers a wide range of topics including Components, Angular Directives, Angular Services, Pipes, security fundamentals, Routing, and Angular programmability. The new Angular TRaining will lay the foundation you need to specialise in Single Page Application developer. Angular Training

    ReplyDelete