wtorek, 21 grudnia 2010

Contexts and Dependency Injection – część II

Drugi z serii wpisów na temat CDI poświęcony będzie zdarzeniom. Pozwalają one luźno powiązać ze sobą bean'y na zasadzie Akcja → Reakcja.
Załóżmy, że nasza aplikacja chce odnotować w dowolnym miejscu moment operacji na obiekcie użytkownika. Należy w tym celu wstrzyknąć obiekt javax.enterprise.event.Event i wywołać na nim metodę fire(). Jej argumentem, będzie obiekt, który ma podlegać obserwacji.
@Named
@RequestScoped
public class UserBean{

    private List users;

    @Inject
    Event createUserEvent;


    @PostConstruct
    private void init(){
        
        users = new ArrayList();
        users.add(new User("Nowak"));
        users.add(new User("Lis"));
    }

    public void addUser(){

        User user = new User("Kowalski");
        users.add(user);
        createUserEvent.fire(user);
    }
}

Teraz wystarczy już w dowolnym miejscu aplikacji zaimplementować metodę nasłuchującą, będącą odbiorcą powyższego zdarzenia
@Named
@RequestScoped
public class UserObserver {

    public void onCreateUser(@Observes User user){

        System.out.println(">> User "+ user.getName() + " has been created");
    }
}

A co w przypadku gdybyśmy chcieli obserwować kilka różnych zdarzeń na obiekcie User ? Tutaj znowu z pomocą przychodzą kwalifikatory
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface CreateUser {
}
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface DeleteUser {
}

Zmodyfikowana klasa obserwująca
import javaspotlight.qualifiers.CreateUser;
import javaspotlight.qualifiers.DeleteUser;
import javax.enterprise.event.Observes;
import javax.faces.bean.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class UserObserver {

    public void onCreateUser(@Observes @CreateUser User user){

        System.out.println(">> User "+ user.getName() + " has been created");
    }

    public void onDeleteUser(@Observes @DeleteUser User user){

        System.out.println(">> User "+ user.getName() + " has been deleted");
    }
}

Sposób inicjacji zdarzeń – oczywiście nie muszą znajdować się one w tej samej klasie
import java.util.ArrayList;
import java.util.List;
import javaspotlight.qualifiers.CreateUser;
import javaspotlight.qualifiers.DeleteUser;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.faces.bean.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@RequestScoped
public class UserBean{

    private List users;

    @Inject
    @CreateUser
    Event createUserEvent;

    @Inject 
    @DeleteUser
    Event deleteUserEvent;

    @PostConstruct
    private void init(){
        
        users = new ArrayList();
        users.add(new User("Nowak"));
        users.add(new User("Lis"));
    }

    public void addUser(){

        User user = new User("Kowalski");
        users.add(user);
        createUserEvent.fire(user);
    }

    public void removeUser(){

        for(User user : users){
     
            if("Nowak".equals(user.getName())){

                deleteUserEvent.fire(user);
                users.remove(user);
            }
        }
    }