Next Generation Application Development: Fortgeschrittene Konzepte

Stereotypes

Stereotypes können dafür verwendet werden ein Set von Annotationen zusammenzufassen. Dies erlaubt es Entwicklern, Stereotypes für Applikationen zu erstellen, die einen Großteil des gewünschten Standardverhaltens abdecken. Stereotypes kombinieren einen Scope und verschiedene Interceptor Bindings. Dadurch können mehrere Annotationen an den Beans durch eine Einzige ersetzt und die Annotation Hell unter Kontrolle gebracht werden. Anstatt eine Bean mit vielen CDI-Annotationen anzureichern, reicht ein Stereotype, der diese CDI-Annotationen abdeckt. Wie im nächsten Beispiel zu sehen wird das Interface Action mit @javax.enterprise.inject.Stereotype annotiert, zusammen mit @RequestScoped und @Named.

@Stereotype
@RequestScoped
@Named
@Retention(RUNTIME)
@Target(TYPE)
public @interface Action {}

Alle Beans, die jetzt mit dem Stereotype @Action annotiert werden, erben automatisch @RequestScoped und @Named. Die Stereotype-Annotation wird direkt an der Bean verwendet. Die Scope-Annotation kann jeder Zeit an der Bean selbst überschrieben werden, sollte dies notwendig sein.

@Action 
public class RegisterUserAction { 
... 
}

Stereotypes können zudem kombiniert werden. Das macht unter Umständen Sinn, wenn zwei Stereotypes existieren, die für sich alleine existieren können, aber unter gewissen Umständen kombiniert werden sollen. Im nächsten Beispiel ist das @AuditableAction Stereotype mit @Action und @Auditable annotiert. Das @Action Stereotype ist wie zuvor mit @RequestScoped und @Named annotiert. Des Weiteren gibt es ein zweites Stereotype @Auditable, der wiederum Interceptors für das Logging verwenden kann. Dadurch werden applikationsübergreifende technische Aufgaben besser von der Geschäftslogik getrennt.

@Stereotype
@Action
@Auditable
@Target(TYPE)
@Retention(RUNTIME)
public @interface AuditableAction {}

Die CDI-Spezifikation liefert zudem Standard-Stereotypes, die wir in diesem Artikel zum Teil schon beschrieben haben: @Interceptor, @Decorator und @Model. Das @Model Stereotype kann für Webapplikationen (z. B. JSF) an Stelle von Managed Beans verwendet werden.

@Stereotype
@Named 
@RequestScoped 
@Target({TYPE, METHOD}) 
@Retention(RUNTIME) 
public @interface Model {}

Stereotypes können auch Interceptor Bindings definieren. Dadurch werden technische Aufgaben wie Transaktionen und Sicherheit besser von der Geschäftslogik gekapselt.

@Stereotype
@RequestScoped
@Transactional(requiresNew=true)
@Secure
@Retention(RUNTIME)
@Target(TYPE)
public @interface Action {}
Alternatives

Im ersten Artikel dieser Serie haben wir Alternatives vorgestellt, die über die beans.xml aktiviert werden können. Dadurch konnten einzelne Beans während der Deployment-Phase ausgetauscht werden.

@Alternative 
public class AlternativeUserRegistrationService implements UserRegistrationService {
  ...
}

Für den Fall, dass z. B. für Staging Tests mehrere Beans gleichzeitig ausgetauscht werden sollen, empfiehlt es sich einen Stereotype @Staging einzuführen.

@Stereotype
@Alternative
@Retention(RUNTIME)
@Target({TYPE})
public @interface Staging {}

Dieser Stereotype annotiert alle Alternative Beans, die für Staging Tests ausgetauscht werden sollen.

@Staging
public class StagingUserRegistrationService implements UserRegistrationService {
  ...
}

In der beans.xml wird dann nur noch der @Staging Stereotype aktiviert, und alle Staging Beans werden aktiviert.

de.sample.alternatives.Staging
Spezialisierung

Bei der Verwendung von @Alternative können sich Fehler in der Programmierung einschleichen. Wenn die Default-Implementierung einer Bean einen Qualifier, eine Producer-Methode oder eine Observer-Methode besitzt und die Alternative Bean diese nicht komplett überschreibt, könnte der Fall eintreten, dass die Default Bean dennoch aufgerufen wird. Um sicher zu gehen, dass dies unter keinen Umständen geschieht, sollte @Specializes verwendet werden. In diesem Fall muss die Alternative Bean die Default-Implementierung der Bean erweitern und erhält somit alle Qualifier. Sollte die Bean mit @Named annotiert sein und einen EL-Namen besitzen, würde auch dieser von der Alternative Bean geerbt werden.

@Alternative @Specializes
public class MockUserRegistrationService extends UserRegistrationServiceImpl {
  ...
}
Zusammenfassung

Die hier vorgestellten Konzepte machen es dem Entwickler einfach, typsichere und modulare Java-Enterprise-Anwendungen zu schreiben. Der Einsatz von Interceptors für Crosscutting Concerns und Decorators für Erweiterungen der Geschäftslogik sind bewährte Design Patterns in Enterprise-Anwendungen, die mit CDI sehr einfach umgesetzt werden können. Die Eventverarbeitung in CDI mit dem Producer/Observer-Konzept ist ebenfalls sehr gut gelungen und überzeugt durch die Entkopplung von Producer und Observer zur Kompilierzeit. Auch die Bindung von Events an Transaktionsphasen bietet in der Praxis einen großen Vorteil. Eine komplette Trennung von EJB ist leider noch nicht möglich, da z. B. die asynchrone Verarbeitung der Observer-Methoden für Events nicht durch CDI unterstützt wird. Die hier vorgestellten Konzepte lassen das große Potenzial von CDI erkennen, das wir im nächsten Artikel „Guru – Framework-Integration“ weiter aufzeigen werden.

Daniel Arndt arbeitet für die M-net Telekommunikations GmbH als Senior Software Entwickler und Software Architekt. Er beschäftigt sich seit 10 Jahren vorrangig mit dem Entwurf und der Realsierung von Java Enterprise Applikationen.

Marcel Birkner studierte an der Hochschule Bonn-Rhein-Sieg und der York University in Toronto mit dem Schwerpunkt in Software Architektur und Design. Er arbeitet für die M-net Telekommunikations GmbH als Software Entwickler und beschäftigt sich mit der Einführung von Java EE 6 für Teile der IT-Landschaft.

Kommentare

Schreibe einen Kommentar

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