no tier enterprise applications with cdi
DESCRIPTION
Der Einsatz von Java EE führt meist zu Anwendungen, die einer klassischen serviceorientierten Mehrschichtarchitektur entsprechen. Mit Java EE 6 und CDI (JSR 299 aka WebBeans) hält nun ein Entwicklungsparadigma Einzug, das diesen Designansatz zugunsten des fachlichen Domain-Modells grundlegend verändern kann. "Business Injection" statt "Infrastructure Injection" ist das zugehörige Zauberwort. Die Session zeigt, wie eine klassische Mehrschichtwebanwendung durch die Einführung von fachlicher Dependency Injection, asynchroner bzw. eventorientierter Kommunikation und Ansätzen der aspektorientierten Programmierung verbessert werden kann und dabei mit standardisierten Mitteln ein neues Zeitalter der effizienten, wartbaren und performanten Anwendungsarchitektur einläutet.Speaker: Lars Röwekamp17.04.2012 | 10:00 - 11:15 | JAX, MainzTRANSCRIPT
No-Tier EnterpriseApplications with CDI
Lars Röwekamp | open knowledge GmbH
@mobileLarson@_openknowledge
> Cool! JavaEE bietet IoC/DI > Cool! JavaEE bietet IoC/DI > Cool! JavaEE bietet IoC/DI > Cool! JavaEE bietet IoC/DI
> Aber was ändert sich?> Aber was ändert sich?
> SCHICHT 2
> SCHICHT 1TX Grenze
> SCHICHT 3
> SCHICHT 2
Einmal den Customer Controller, bitte ;-)
Und für mich den Customer Service, bitte!
Ok, dann brauch ich nen Customer Entity mit der internene ID 147122, aber flott!
> UseCase: ausgewählten Kunden bearbeiten
AA KK TT UU EE LL LL
AA UU SS GG EE WW ÄÄ HH LL TT EE
KK UU NN DD EE
RR
> Was wäre wenn ...? > Was wäre wenn ...? > Was wäre wenn ...? > Was wäre wenn ...?
KK UU NN DD EE
LL II SS TT EE
MM EE II NN EE RR
EE II NN KK ÄÄ UU
> Oder wenn ...? > Oder wenn ...? > Oder wenn ...? > Oder wenn ...?
FF EEEE II NN KK ÄÄ UU FF EE
> „No-Tier“
TX Grenze
> „No-Tier“
J2EE 1.3 (JSR 58):
September 2001
� Servlet 2.3
� JSP 1.2
� EJB 2.0
01 / 02 03 / 04 05 / 06 07 / 08 09 / 10
Spring V1
Juni 2003
Java EE v5 (JSR 244):
Mai 2006
� Servlet 2.5
� JSP 2.1 / JSF 1.2
� EJB 3.0
Spring V3
Dezember 2009
J2EE 1.4 (JSR 151):
November 2003
� Servlet 2.4
� JSP 2.0
� EJB 2.1
01 / 02 03 / 04 05 / 06 07 / 08 09 / 10
„Spring“
Oktober 2002
Java EE v6 (JSR 316):
Dezember 2009
� Servlet 3.0
� JSP 2.1 MR / JSF 2.0
� EJB 3.1
� JPA 2.0
� CDI 1.0
Spring V2
Oktober 2006
Enterprise JavaBeans
Life Cycle Mmgt.
Instance Pooling
Concurrency
TransactionTransaction
Security
Scoping
...
EJBs: Schwergewichtig
CDI:
Leichtegichtig CDI Beans
Life Cycle Mmgt.
Scoping
... AND ...
*** Extensibility ***
CDI Konzepte
Typensicher DI
(Stereotypes, Qulifier)
Loose Koopelung
CDI:
Leichtegichtig
(Events, Interceptors)
Sichtbarkeiten
(Sopes, LifeCycle )
„FACHLICHE INJECTION“
> DI/IoC lite„Java EE without EJB“
> DI/IoC advancedLifeCyle Managementund Scoping
CDI Kickstart
> DI/IoC eXtremeTypensicherheit undlose Koppelung
> DI/IoC openExtension-Mechanismus
Base Features
Base Features
> @Inject> @Named> Sterotypes> Sterotypes> Alternatives
Base Features
> Sope Singleton> Cleanup> Request> Conversation> Conversation> Session> Application> Dependant*> Singleton*
*Pseudo-Scope
Base Features
Base Features
Base Features
> Events> Events> Observer> Interceptors
Base Features
> Qualifier> Stereotypes> Alternatives
> Was haben wir gewonnen?> Was haben wir gewonnen?> Was haben wir gewonnen?> Was haben wir gewonnen?
> SCHICHT 2
> SCHICHT 1
> SCHICHT 3
> SCHICHT 2
> SCHICHT 2
> SCHICHT 1
> SCHICHT 3
> SCHICHT 2
import javax.inject.Named;import javax.inject.Inject;import javax.enterprise.context.RequestScoped;
@Named(“hello “)@RequestScopedpublic class HelloBean {
CDI Managed Bean
„hello“ für EL„hello“ für EL
gültig für Requestgültig für Requestpublic class HelloBean {
@Inject Greeter greeter ;
private String name;
public String getGreeting() {return greeter .greet( name);
}
// getter and setter for name attribute...}
Injection PointInjection Point
public class Greeter {
public String greet(Sting name) {
if ( name != null) {return “Hello, “ + name;
CDI Managed BeanSimple POJOSimple POJO
return “Hello, “ + name; } else {
return “Hello, stranger!“; }
}}
CDI Managed Bean
@Statelesspublic class GreeterEJB
implements Greeter {
private static final Log logger = ...
@Inject @Current CrmUser crmUser;
Stateless EJBStateless EJB
@Inject @Current CrmUser crmUser;
public String greet(Sting name) {
logger. debug(“Who: “ + crmUser.getName());
if ( name != null) {... // create & return greeting
}}}
Cool, aber geht da
nicht mehr?
CDIMehrwert
FACHLICHE Injektion statt „nur“
Infrastruture Injection
eCustomer - Beispiel
CDI Refactoring
> CDI Wiring
> CDI Current User
> CDI Beans only> CDI Beans only
> CDI Style Views
> CDI Events
CDI Refactoring
> CDI Wiring
> CDI Current User
> CDI Beans only> CDI Beans only
> CDI Style Views
> CDI Events
CDI Refactoring
> CDI Wiring
> CDI Current User
> CDI Beans only> CDI Beans only
> CDI Style Views
> CDI Events
eCustomer - CDI Current User
> Producer Methods & Fields
> „Factory Method“ Pattern für Objekte
> @Produces als Mittel zum Zweck
> @Qualifier als Mittel zur Qualifizierung
> Ermöglicht nicht nur Infrastruktur
sondern vor allem auch fachliche
Injection.
eCustomer - CDI Current User
@Named@SessionScopedpublic class AuthenticationController
implements Serializable {
private User authenticatedUser;
AuthenticationControllerAuthenticationController
public String authenticate() {...}
public User getAuthenticatedUser() {...}
...}
@Produces @Current
eCustomer - CDI Current User
@Named@SessionScopedpublic class AuthenticationController
implements Serializable {
private User authenticatedUser;
public String authenticate() {...}
@Produces@Currentpublic User getAuthenticatedUser() {...}
...} @Inject @Current User user; @Inject @Current User user;
@RequestScoped
eCustomer - CDI Current User
package de.openknowledge.qualifier;
import ...
@Qualifier@Target({TYPE, METHOD, PARAMETER, FIELD})@Retention(RUNTIME)
Self-made QualifierSelf-made Qualifier
@Retention(RUNTIME)public @interface Current {}
eCustomer - CDI Current User
@javax.inject. [email protected]. SessionScopedpublic class CustomerBean implements Serializable {
// @javax.inject. Inject // private AuthenticationController authController ;
JSF CustomerBean JSF CustomerBean
@javax.inject. Injectprivate CustomerService customerService ;
public String update () {// User currentUser =
authController .getAuthenticatedUser();// currentCustomer .updateAuditInformation(currentUser);
customerService .updateCustomer(currentCustomer);return Outcome.SUCCESS;
}...
}
Audit „Bereinigung“Audit „Bereinigung“
Use Case „Kunde bearbeiten“
@Statelesspublic class CustomerServiceEJB
implements CustomerService {
@Inject @Currentprivate User currentUser;
CustomerService EJBCustomerService EJB
@PersistenceContextprivate EntityManager em;
// updates the customer - needs a transactionpublic Customer updateCustomer(Customer customer)
{customer.updateAuditInformation(currentUser);return em.merge(customer);
}}
CDI Refactoring
> CDI Wiring
> CDI Current User
> CDI Beans only> CDI Beans only
> CDI Style Views
> CDI Events
eCustomer - CDI Beans only
> Injizierbare CDI Ressourcen
> „normale“ Java Klassen, optional mit
@Named oder @Qualifier markiert
> EJBs, wie Stateless, Stateful, Singleton
> Sonstige Java EE Ressourcen, wie
PersistenceContext, UserTransaction
eCustomer - CDI Beans only
@Stateless// no annotation required!public class CustomerService BeanEJB
implements CustomerService {
@Inject @Currentprivate User currentUser;
CustomerService CDICustomerService CDI
private User currentUser;
@PersistenceContextprivate EntityManager em;
// updates the customer - needs a transactionpublic Customer updateCustomer(Customer customer)
{customer.updateAuditInformation(currentUser);return em.merge(customer);
}
...
}
eCustomer - CDI Beans only
@Stateless// no annotation required!public class CustomerService BeanEJB
implements CustomerService {
@Inject @Currentprivate User currentUser;
CustomerService CDICustomerService CDI
private User currentUser;
@PersistenceContextprivate EntityManager em;
// updates the customer - needs a transactionpublic Customer updateCustomer(Customer customer)
{customer.updateAuditInformation(currentUser);return em.merge(customer);
}
...
}
Und Transaktionen?!Und Transaktionen?!
Bauen wir uns selbst ...Bauen wir uns selbst ...
eCustomer - CDI Beans only
// simple pojo // no annotation required!public class CustomerServicBean
implements CustomerService {
@Inject @Currentprivate User currentUser;
CustomerService CDICustomerService CDI
private User currentUser;
@PersistenceContextprivate EntityManager em;
@Transactionalpublic Customer updateCustomer(Customer customer)
{customer.updateAuditInformation(currentUser);return em.merge(customer);
}
...
}
CDI Interceptors
eCustomer - CDI Beans only
@InterceptorBinding@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Transactional {
@Nonbinding
??@Nonbindingpublic TransactionalType value ()
default TransactionalType.REQUIRED;
}
Transactional AnnotationTransactional Annotation
eCustomer - CDI Beans only
@Transactional @Interceptorpublic class TransactionAdvice {
@Injectprivate UserTransaction utx;
Transactional Interceptor*Transactional Interceptor*
@AroundInvokepublic Object applyTransaction(
InvocationContext ic ) throws Throwable {
... // 1. access @Transactional,// if needed
... // 2. implement utx.begin()ic.proceed(); // 3. call original method... // 4. implement utx.commit()
} } *XML registration omitted
eCustomer - CDI Beans only
@Transactional @Interceptorpublic class TransactionAdvice {
@Injectprivate UserTransaction utx;
Transactional Interceptor*Transactional Interceptor*
@AroundInvokepublic Object applyTransaction(
InvocationContext ic ) throws Throwable {
Transactional tx = ic.getMethod(). getAnnotation(Transactional.class);
... // 2. implement utx.begin()ic.proceed(); // 3. call original method... // 4. implement utx.commit()
} } *XML registration omitted
eCustomer - CDI Beans only
// no annotation required!public class CustomerServiceBean
implements CustomerService {
@Inject @Currentprivate User currentUser;
CustomerService CDICustomerService CDI
@PersistenceContextprivate EntityManager em;
@de.openknowledge.qualifier. Transactionalpublic Customer updateCustomer(Customer customer)
{customer.updateAuditInformation(currentUser);return em.merge(customer);
}...
}
inkl. Transaktioninkl. Transaktion
> SCHICHT 2
> SCHICHT 1TX Grenze
> SCHICHT 3
> SCHICHT 2
> SCHICHT 2
> SCHICHT 1
TX Grenze
> SCHICHT 3
> SCHICHT 2
eCustomer - CDI Beans only
@Named@SessionScopedpublic class CustomerBean implements Serializable {
@Injectprivate CustomerService customerService ;
CustomerBean CDICustomerBean CDI
@de.openknowledge.qualifier. Transactionalpublic String update () {
customerService .updateCustomer(currentCustomer);... // some additional use case “tx“ related
workreturn Outcome.SUCCESS;
}...
}
inkl. „fachliche“ Transaktioninkl. „fachliche“ Transaktion
CDI Refactoring
> CDI Wiring
> CDI Current User
> CDI Beans only> CDI Beans only
> CDI Style Views
> CDI Events
eCustomer - CDI Style Views
> CDI Conversations
> @ConversationScoped
> conversation.begin() / .end()
> CDI „Backing Beans“
> @Produces in Kombination mit @Named
> „self-made“ Qualifier
eCustomer - CDI Style Views
@javax.inject. [email protected]. ConversationScopedpublic class CustomerBean implements Serializable {
private Customer customer;
@javax.inject .Inject
CustomerBean (1/2)CustomerBean (1/2)
@javax.inject .Inject private Conversation conversation ;
public String selectCustomer (Customer customer) {conversation.begin();this.customer = customer;return ... ;
}...
}
eCustomer - CDI Style Views
@javax.inject. [email protected]. ConversationScopedpublic class CustomerBean implements Serializable {
private Customer customer;
@javax.inject .Inject
CustomerBean (2/2)CustomerBean (2/2)
@javax.inject .Inject private Conversation conversation ;
public String updateCustomer () {...conversation.end(); return ... ;
}...
}
Conversation endet mit RequestConversation endet mit Request
eCustomer - CDI Style Views
<html ...><h:body>
<h:form>
Vorname: <h:inputText value=“ #{ customerBean .customer.firstname} "/>
Name: <h:inputText
Infrastructure in der View!Infrastructure in der View!
Name: <h:inputText value=“ #{ customerBean .customer.lastname} "/>
</h:form></h:body>
</html>
eCustomer - CDI Style Views
<html ...><h:body>
<h:form>
Vorname: <h:inputText value=“ #{ selectedCustomer .firstname} "/>
Name: <h:inputText
Fachlichkeit in der View!Fachlichkeit in der View!
Name: <h:inputText value=“ #{ selectedCustomer .lastname} "/>
</h:form></h:body>
</html>
eCustomer - CDI Style Views
@javax.inject. [email protected]. ConversationScopedpublic class CustomerBean implements Serializable {
private Customer customer ;
@javax.inject. Produces
CustomerBean CustomerBean
@javax.inject. [email protected]. Named(“ selectedCustomer “)@de.openknowledge.qualifier. Selectedpublic Customer getSelected {
return customer ; }...
}
CDI Refactoring
> CDI Wiring
> CDI Current User
> CDI Beans only> CDI Beans only
> CDI Style Views
> CDI Events
eCustomer - CDI Events
> Java EE Observer Pattern, inkl. ...
> Event Object & Event Producer
> Observer Method
> „besondere“ Eigenschaften
> schichtenneutral auch für POJOs
> (ggf.) transaktionsgebunden
> synchrone Interaktion
eCustomer - CDI Events
„User created!“„User created!“
„Und ich auch!“„Und ich auch!“„Ah, interessant.“„Ah, interessant.“
„Finde ich!“„Finde ich!“
eCustomer - CDI Events
> Ok, aber ...
> Wie sieht ein solches Event aus?
> Und wie fange ich es?
> Und vor allem: wie löse ich es aus?
eCustomer - CDI Events
public class CustomerCreatedEvent {
private Customer customer;
public CustomerCreatedEvent (Customer customer) {
Customer Created Event (1/3)Customer Created Event (1/3)
public CustomerCreatedEvent (Customer customer) {this.customer = customer;
}
public Customer getCustomer() { ... }}
„Wie sieht ein solches Event aus?“
eCustomer - CDI Events
public void sendWelcomeMail(@Observes CustomerCreatedEvent event ) {
Customer customer = event.getCustomer () ;
Customer Created Event (2/3)Customer Created Event (2/3)
Customer customer = event.getCustomer () ;...
}
„Und wie fange ich es?“
eCustomer - CDI Events
@Injectprivate Event<CustomerCreatedEvent> eventSource ;
public String createCustomer() {
Customer Created Event (3/3)Customer Created Event (3/3)
Customer customer = ...;
eventSource.fire (new CustomerCreatedEvent( customer )
) ;
...}
„Und vor allem: Wie löse ich es aus?“
eCustomer - CDI Events
„Wird das Event Object tatsächlich benötigt oder gibt es eventuell noch Alternativen?“
„Nicht unbedingt, man kann auch sehr gut mit eigenen
Qualifiern arbeiten!“
eCustomer - CDI Events
@Qualifier@Target({TYPE, METHOD, PARAMETER, FIELD})@Retention(RUNTIME)public @interface Created {}
Qualified CDI Event (1/3)Qualified CDI Event (1/3)
eCustomer - CDI Events
public void sendWelcomeMail(@Observes CustomerCreatedEvent event@CreatedCustomer customer ) {
Qualified CDI Event - Alternative (2/3)Qualified CDI Event - Alternative (2/3)
Customer customer ) {
Customer customer = event.getCustomer();...
}
„Und wie fange ich es?“
eCustomer - CDI Events
@Inject @Createdprivate Event<Customer> eventSource;
public String createCustomer() {
Qualified CDI Event - Alternative (3/3)Qualified CDI Event - Alternative (3/3)
Customer customer = ...; eventSource.fire(customer);
...}
„Und vor allem: Wie löse ich es aus?“
eCustomer - CDI Events
„Wow! Observer mit Qulifiern -das muss ich erst einmal sacken lassen!“
„Und das ist erst die Spitze des Eisberges - schau dir mal die CONDITIONAL OBSERVER
METHODS hier an!“
eCustomer - CDI Events
// Conditional Observer Method that takes // - Transaction status , e.g. AFTER_SUCCESS, AFTER_FAILURE// - Bean instance status , e.g. ALLWAYS// into accountpublic void sendWelcomeMail(
Conditional Observer MethodsConditional Observer Methods
public void sendWelcomeMail(@Observes(
receive=ALLWAYS, // beanduring=AFTER_SUCCESS // tx
)@Created Customer customer) {
... }
> „No-Tier“
TX Grenze
> „No-Tier“
XFazit:
CDI Fazit
CDI ermöglicht ...
“Java Enterprise Development without EJB -and without Spring“
CDI bietet dafür ...
„typesafe und schichtenneutrales Injection Framework für fachliche und technische Injection sowie ein Rahmenwerk für eventgetriebene Entwicklung.“
@mobileLarson@_openknowledge
facebook.com/openknowledge
Gibt es noch Fragen?
Dann los ...