Guru – Framework-Integration

CODI

CODI ist ein MyFaces-Extensions-Projekt, das Portable Extensions für die Java-Plattform (SE und EE) entwickelt [3]. Wie CDI legt auch CODI Wert auf Typsicherheit und Erweiterbarkeit. Der Schwerpunkt liegt auf Werkzeugen, die bei der Lösung täglicher Bedürfnisse der Software-Entwicklung mit CDI, JSF, JPA und Bean Validation helfen sollen. Zu den wichtigsten Features von CODI zählen vordefinierte ConversationScopes für MyFaces-Applikationen.

  • @ConversationScoped
  • @WindowScoped
  • @ViewAccessScoped

Der CDI ConversationScope besitzt ein paar Nachteile, die CODI mit seinen Scopes überarbeitet hat. In CDI gibt es zum Beispiel nur eine große Conversation, die alle Conversation Beans enthält. In CODI hingegen existiert jede ConversationScoped Bean standardmäßig in einer isolierten Conversation. Daher ist es in CDI nur möglich, die Conversation komplett zu beenden, allerdings nicht für einzelne Beans. Zudem erlaubt die CDI Conversation nicht das Wiederherstellen von Conversations während eines Requests und die Conversation muss immer explizit gestartet werden. Um Beans zusammenzufassen, gibt es in CODI das Konzept der ConversationGroup, das in Listing 4.2 erläutert wird. Die CODI Scopes versuchen einen Großteil von typischen Anwendungsfällen in Applikationen abzudecken und dabei die Probleme des CDI ConversationScope zu beheben [4].

Als Erstes wird in den folgenden Beispielen die Verwendung von ConversationScoped Beans erläutert. Sobald eine mit @ConversationScoped annotierte Bean aufgerufen wird, startet eine Conversation. Für JSF-Applikationen muss die Bean mit @Named annotiert sein. ConversationScoped Beans verwenden standardmäßig einen Time-out von 30 Minuten. Dieser Timer setzt sich automatisch zurück, sobald eine Bean verwendet wird. Die Standard-Konfigurationsparameter können in org.apache.myfaces.extensions.cdi.javaee.jsf.api.ConfigParameter überschrieben werden.

@Named
@ConversationScoped
public class ConversationScopedBean implements Serializable {
    public String getContent() {
   	 return "Conversation Scoped Bean";
    }
}

Wenn eine Conversation beendet werden soll, zum Beispiel wenn ein Bestellprozess angeschlossen ist, kann die aktuelle Conversation in die @ConversationScoped Bean injiziert und manuell geschlossen werden.

@Named
@ConversationScoped
public class ProductOrderConversation implements Serializable {
    
    @Inject private Conversation conversation;
    
    public void sendOrder() {
        this.conversation.close();
    }
}

WindowScoped Beans verhalten sich wie ConversationScoped Beans, mit dem Unterschied, dass es keinen Time-out gibt. Daher sind sie vergleichbar mit SessionScoped Beans, bei denen der Context manuell zurückgesetzt werden kann. Zudem sind WindowScoped Beans pro Fenster eindeutig.

@WindowScoped
public class WindowScopedBean implements Serializable {
}

Die Lebensdauer von ViewAccessScoped Beans hängt direkt vom View ab. Sie besitzen auch keinen Time-out. Ansonsten sind sie vergleichbar mit ConversationScoped Beans. Wenn ViewAccessScoped Beans innerhalb eines Views nicht weiter verwendet werden, räumt der CDI Container sie automatisch auf.

@ViewAccessScoped
public class ViewAccessScopedBean implements Serializable {
}

Um ConversationScoped Beans zusammenfassen zu können, gibt es das Konzept der ConversationGroups. Eine ConversationGroup kann eine Marker-Klasse oder ein Interface sein (Listing 4.1). Umgesetzt wird eine ConversationGroup mit dem CDI Qualifier @ConversationGroup. Wenn keine ConversationGroup für eine Bean explizit definiert wurde, wird der Name der Bean als Gruppenname verwendet (Listing 4.2).

Listing 4.1: ConversationGroup-Marker-Interface
public interface ProductOrderConversationGroup {
}
Listing 4.2: Verwendung von ConversationGroups
@ConversationScoped
@ConversationGroup(ProductOrderConversationGroup.class)
public class ProductOrderBean implements Serializable {
    
    @Inject private Conversation conversation;
    
    public void sendOrder() {
        this.conversation.close();
    }
}

Um alle Conversations in einer ConversationGroup zu schließen, kann der WindowContext verwendet werden.

public class Bean {
    
    @Inject private WindowContext wc;
    
    public void sendOrder() {
        this.wc.closeConversationGroup(ProductOrderConversationGroup.class);
    }
}

Ein weiteres nützliches Werkzeug für den Entwickler ist die Bean Validation mit dem MyFaces Extensions Validator (ExtVal) . MyFaces ExtVal ist ein JSF-Validation-Framework, mit dem Felder mit Constraints für die Validierung annotiert werden können. Es bietet eine Integration mit Bean Validation Frameworks, die den JSR-303-Standard implementieren (z. B. Hibernate Validator und Apache Bean Validation). Wenn ExtVal in Verbindung mit CODI genutzt wird, verwendet es die ValidatorFactory von CODI und funktioniert somit „out of the box“.

Im folgenden Beispiel der Customer-Bean wurden mehrere Felder mit Constraints annotiert, in diesem Fall mit @NotNull, @Size, @Min, @Max und @Pattern. CODI injiziert den Validator direkt in die Bean während der Laufzeit und bei dem Aufruf von validateCustomer()werden alle Felder validiert, die mit einem Constraint annotiert sind. Im Fall eines Fehlers kann eine entsprechende Nachricht im MyFaces Context hinzugefügt werden.

Listing 5: Bean Validation mit ExtVal
@Model
public class Customer {

    @NotNull
    @Size(min=1,max=30)
    private String name;
    
            @NotNull
    @Pattern(regexp=".+@.+\.[a-z]+")
    private String email;

    @Min(value=18, message="You must be {value} years old to become a customer.")
    private int age;
    
    private Validator validator;
            private FacesContext facesContext;

    @Inject
    public Customer(@Advanced Validator validator, FacesContext facesContext) {
            this.validator = validator;
            this.facesContext = facesContext;   	 
    }
    
    public void validateCustomer() {
        Set> violations = validator.validate(this);

        if( !violations.isEmpty() ) {
            ConstraintViolation violation = violations.iterator().next();
                String message = violation.getMessage();
                this.facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
        }
    }

    // getter / setter
}

Aktuell liegt CODI in der Version 0.9.4 vor, Version 1.0.0 ist für das dritte Quartal in diesem Jahr geplant. Es zählt zu den wichtigsten Projekten, mit denen sich JSF-Entwickler auseinandersetzen sollten.

 

Tabelle 2: Überblick der CODI-Module

Modul Beschreibung

JSF 1.2/2.0

Erweiterung der JSF-Funktionalität, zusätzliche Scopes, Lifecycle Listener, Producers für JSF-Artefakte, Producers für CODI-Artefakte, Type-safe View Config, Type-safe Navigation, Type-safe Security etc.

JPA

Bietet JPA-Transaktionen auch außerhalb eines JEE-Containers.

Bean Validation (JSR-303)

Erlaubt Dependency Injection in Constraint Validators für JSR-303 Validation Frameworks.

Scripting (JSR-223)

Typsichere Injizierung der JSR-223 API

Message (I18N)

Bietet serialisierbare Messages mit einer Fluent API und lokalisierbare Messages, die auch für andere Java-Frameworks verwendet werden können.

.

 

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.