Date post: | 23-Jun-2015 |
Category: |
Environment |
Upload: | open-knowledge-gmbh |
View: | 207 times |
Download: | 3 times |
Voodoo Architecture
@mobileLarson @_openKnowledge
Lars Röwekamp | CIO New Technologies
„Fachlichkeit im Fokus!“ !
„Java EE 6 und 7 erlauben neben
Infrastructure Injection auch
Business Injection.“
Was sie mitnehmen sollten ...Voodoo powered Enterprise Architecture
Ok, was heißt das?
Voodoo powered
Call Center Anwendung !
‣ Kunde neu erfassen und speichern ‣ Call Center Agent als Audit Info mit speichern ‣ Begrüßungs-EMail an Neukunden versenden !
‣ Kunde löschen inkl. Sicherheitsabfrage ‣ Call Center Agent als Audit Info mit speichern ‣ EMail an ehemaligen Kunden versenden
Der Use CaseEnterprise Architecture
Old School
Voodoo powered
Use Case: Kunde neu erfassen !
‣ JSF View ruft UI Controller via U-EL ‣ UI Controller ruft CustomerService EJB ‣ UI Controller ruft MailService EJB
Enterprise ArchitectureOld School Ansatz
Voodoo powered Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View
CreateCustomer
CustService MailService
Customer Mail
Enterprise ArchitectureOld School Ansatz
// JSF UI [email protected][email protected](name=“createCustomerController“)!public class CreateCustomerController {!! @EJB! private CustomerService customerService; !!
@EJB ! private MailService mailService; ! ! private Customer customer; !
! public String createCustomer() {!
customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED; !} !!// getter / setter for customer!...!
}!
Und was ist mit dem Call Center Agent?
Voodoo powered
Use Case: Kunde neu erfassen !
‣ JSF View ruft UI Controller via U-EL ‣ UI Controller ruft CustomerService EJB ‣ UI Controller ruft MailService EJB ‣ UI Controller ruft AuthenticationController
Enterprise ArchitectureOld School Ansatz
Voodoo powered
Enterprise ArchitectureOld School Ansatz
JSF View
CreateCustomer
CCAgent
AuthService
MailService
Customer
CustService
AuthController
Voodoo powered
Enterprise ArchitectureOld School Ansatz
// JSF UI [email protected][email protected](name=“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @EJB!!
@ManagedProperty(value=“#{authenticationController}“) ! private AuthenticationController authController; ! ...!
! public String createCustomer() {! CallCenterAgent currentCallCenterAgent;! currentCallCenterAgent = authController.getLoggedInUser(); !
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!
Ok, aber wo wird die Transaktion aufgezogen?
Voodoo powered
Use Case: Kunde neu erfassen !
‣ JSF View ruft UI Controller via U-EL ‣ UI Controller ruft AuthenticationController ‣ UI Controller ruft CustomerFacade EJB ‣ Delegate EJB ruft CustomerService EJB ‣ Delegate EJB ruft MailService EJB
Enterprise ArchitectureOld School Ansatz
Voodoo powered
TX
Enterprise ArchitectureOld School Ansatz
CreateCustomer
CustFacade
AuthService
CCAgent
CustService MailService
Customer Mail
AuthController
Voodoo powered
Enterprise ArchitectureOld School Ansatz
// JSF UI [email protected][email protected](name=“createCustomerController“)!public class CreateCustomerController {!!
@EJB ! private CustomerFacade customerFacade; !! @ManagedProperty(value=“#{authenticationController}“) ! private AuthenticationController authController; ! ! private Customer customer; !
! public String createCustomer() {! CallCenterAgent currentCallCenterAgent;! currentCallCenterAgent = authController.getLoggedInUser(); ! customerFacade.create(customer, currentCallCenterAgent); ! return CUSTOMER_CREATED;! } !
...!}
Voodoo powered
Enterprise ArchitectureOld School Ansatz
// EJB Service Facade!@Stateless!public class CustomerFacade {!! @EJB !
private CustomerService customerService!! @EJB!
private MailService mailService;!! // Transactional by default! public void createCustomer(Customer customer, ! CallCenterAgent currentCallCenterAgent) {!
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); !} ! !...!
}
Fühlt sich nicht gut an! Alternativen sind aber
auch nicht viel schöner!
Voodoo powered
Enterprise ArchitectureOld School Ansatz
JSF View
CustService
CreateCustomer
AuthService
CCAgent
MailService
Customer Mail
AuthController
Voodoo powered
Use Case: Kunde löschen !
‣ JSF View ruft UI Controller via U-EL ‣ UI Controller „merkt“ sich Kunde in Session ‣ UI Controller navigiert zu Bestätigungsseite ‣ UI Controller bekommt Bestätigung ‣ UI Controller ruft CustomerService EJB ‣ ...
Enterprise ArchitectureOld School Ansatz
Voodoo powered
Enterprise ArchitectureOld School Ansatz
UI
Service
Data
JSF View 1
DeleteCustomer
CustService MailService
Customer Mail
JSF View 2
Voodoo powered
Enterprise ArchitectureOld School Ansatz
// JSF UI [email protected][email protected](name=“deleteCustomerController“)!public class DeleteCustomerController implements Serializable {!! // @EJB CustomerService, AuthenticationService and MailService!! private Customer customerToDelete;! ! public String askForDeletion(Customer customer) {! customerToDelete = customer; ! return SHOW_DELETE_CONFIRMATION; !
} !!
public String deleteCustomer() {! ... // call backend services and delete customer! return CUSTOMER_DELETED; !
} !...!
}! Wann kommt der Datensatz aus der Session wieder raus?
Voodoo powered
Problemkind Schichtenmodell !
‣ UI Controller via JSF Managed Beans ‣ Service Facade und Services via EJBs ‣ Persistenz via EntityManager und Entities !
‣ Alles nur Infrastruktur! ‣Wo steckt eigentlich die fachliche Domain?
Enterprise ArchitectureOld School Ansatz
Voodoo powered
Enterprise ArchitectureOld School Ansatz
UI
Service
Data
JSF View
@ManagedBean (JSF)
Session EJB Session EJB
EntityManager Entity
TX
Voodoo powered
Enterprise ArchitectureVoodoo Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
Voodoo powered
Enterprise ArchitectureVoodoo Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
Voodoo powered
Time for Voodoo …
Voodoo Steps: !
‣ „Technology Independence“ ‣ „@Inject Business Objects“ ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
Voodoo Steps: !
‣ „Technology Independence“ ‣ „@Inject Business Objects“ ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
// JSF UI [email protected][email protected](name=“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @EJB!!
@EJB ! private AuthenticationService authenticationService; ! ! private Customer customer; !
! public String createCustomer() {! currentCallCenterAgent = authenticationService.getLoggedInUser(); !
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!
Migration GuideTechnology Independence
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @Inject!!
@Inject! private AuthenticationService authenticationService; ! ! private Customer customer; !
! public String createCustomer() {! currentCallCenterAgent = authenticationService.getLoggedInUser(); !
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!
Migration GuideTechnology Independence
Voodoo powered
Voodoo Steps: !
‣ „Technology Independence“ ‣ „@Inject Business Objects“ ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
CDI Producer Methods & Fields !
‣ Factory Method Pattern für Objekte ‣ @Producer als Mittel zum Zweck ‣ @Qualifier als Mittel zur Typ-Qualifizierung !
‣ ermöglicht fachliche Injektion
@Inject @Current CallCenterAgentMigration Guide
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @Inject!!
@Inject! private AuthenticationService authenticationService; ! ! private Customer customer; !
! public String createCustomer() {! currentCallCenterAgent = authenticationService.getLoggedInUser(); !
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!
Migration Guide@Inject @Current CallCenterAgent
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @Inject!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! private Customer customer; !
! public String createCustomer() {!
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!!
Migration Guide@Inject @Current CallCenterAgent
Voodoo powered
// Authentication Controller!@SessionScoped!@Named(“authenticationController“)!public class AuthenticationController implements Serializable {!!
private CallCenterAgent authenticatedCallCenterAgent; !! public String authenticate() {...}!!
@Produces @Current ! public CallCenterAgent getAuthenticatedCallCenterAgent() {!
return authenticatedCallCenterAgent;!} !!...!
}!!
Migration Guide@Inject @Current CallCenterAgent
@RequestScoped
@Inject @Current CallCenterAgent
Voodoo powered
package de.openknowldege.qualifier!!import ... !!// self-made qualifier to indicate current instance of something!!@Qualifier!@Target({TYPE, METHOD, PARAMETER, FIELD})!@Retention(RUNTIME)!public @interface Current{! !}
Migration Guide@Inject @Current CallCenterAgent
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @Inject!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! private Customer customer; !
! public String createCustomer() {!
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!!
Migration Guide@Inject @Current CallCenterAgent
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! // inject CustomerService and MailService via @Inject!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! private Customer customer; !
! public String createCustomer() {!
customer.setAuditInformation(currentCallCenterAgent);! customerService.create(customer); ! mailService.sendWelcomeMail(customer); ! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!!
Migration Guide@Inject @Current CallCenterAgent
Voodoo powered
// Customer Service EJB!@Stateless!public class CustomerService {!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! @PersistenceContext ! private EntityManager em; !
! // transactional by default ! public void createCustomer(Customer customer) {!
customer.setAuditInformation(currentCallCenterAgent); ! em.persist(customer);!} !!...!
}!!
Migration Guide@Inject @Current CallCenterAgent
Voodoo powered
Voodoo Steps: !
‣ „Technology Independence“ ‣ „@Inject Business Objects“ ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
Injizierbare CDI Ressourcen !
‣ normale Java Klassen - optional mit @Named und/oder @Qualifier markiert ‣ EJBs - Stateless, Stateful, Singleton ‣ sonstige Java EE Resources -
UserTransaction, PersistenceContext, ...
No more EJBsMigration Guide
Voodoo powered
// Customer Service EJB !@Stateless!public class CustomerService {!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! @PersistenceContext ! private EntityManager em; !
! // transactional by default ! public void createCustomer(Customer customer) {!
customer.setAuditInformation(currentCallCenterAgent); ! em.persist(customer);!} !!...!
}!!
Migration GuideNo more EJBs
Voodoo powered
// Customer Service EJB - no annotation required!!@Stateless!public class CustomerService {!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! @PersistenceContext ! private EntityManager em; !
! // transactional by default ! public void createCustomer(Customer customer) {!
customer.setAuditInformation(currentCallCenterAgent); ! em.persist(customer);!} !!...!
}!!
Migration Guide
Ok, aber wo bekommen wie die Transaktion jetzt her?
No more EJBsVoodoo powered
// Customer Service EJB - no annotation required!!@Stateless!public class CustomerService {!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! @PersistenceContext ! private EntityManager em; !
! @Transactional ! public void createCustomer(Customer customer) {!
customer.setAuditInformation(currentCallCenterAgent); ! em.persist(customer);!} !!...!
}!!
Migration Guide
JTA 1.2 oder DeltaSpike oder als Self-Made CDI-Interceptor
No more EJBsVoodoo powered
!@InterceptorBinding!@Target({TYPE, METHOD})!@Retention(RUNTIME)!public @interface Transactional {!!
@Nonbinding! public TransactionalType value() !
default TransactionalType.REQUIRED; ! !
}!!
Migration GuideNo more EJBs
Voodoo powered
!@Transactional !@Interceptor!public class TransactionAdvice {!! @Inject! private UserTransaction utx;!! @AroundInvoke! public Object applyTransaction(! InvocationContext ic) throws Throwable {!! ... // 1. implement utx.begin()! ic.proceed(); // 2. call original method! ... // 3. implement utx.commit()!! } !
Migration GuideNo more EJBs
*XML registration omitted
Voodoo powered
// Customer Service - no annotation required!!public class CustomerService {!!
@Inject @Current! private CallCenterAgent currentCallCenterAgent; ! ! @PersistenceContext ! private EntityManager em; !
! @Transactional ! public void createCustomer(Customer customer) {!
customer.setAuditInformation(currentCallCenterAgent); ! em.persist(customer);!} !!...!
}!!
Migration GuideNo more EJBs
Voodoo powered
Migration Guide
UI
Service
Data
JSF View
UsecaseController
Service Service
EntityManager Entity
TX
No more EJBsVoodoo powered
Migration Guide
UI
Service
Data
JSF View
UsecaseController
Service Service
EntityManager Entity
TX
No more EJBsVoodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! @Inject! private CustomerService customerService;!
! private Customer customer; !
! @Transactional! public String createCustomer() {!
customerService.create(customer); ! ... // some additional use case “tx“ related work! return CUSTOMER_CREATED;!} !!// getter / setter for customer!...!
}!!
Migration GuideNo more EJBs
Voodoo powered
Voodoo Steps: !
‣ „Technology Independence“ ‣ „@Inject Business Objects“ ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
Anti-Pattern „alles in die Session“ !
‣ RequestScoped ist leider zu kurz ‣ ViewScoped irgendwie auch und „JSF only“ ‣ SessionScoped aus Mangel an Alternativen
No more pumped up SessionMigration Guide
‣ ViewScoped ab Java EE 7 auch als „CDI“ ‣ FlowScoped ab Java EE 7
Voodoo powered
Migration GuideNo more pumped up Session
// JSF UI [email protected][email protected](“deleteCustomerController“)!public class DeleteCustomerController implements Serializable {!! // @EJB CustomerService, AuthenticationService and MailService!! private Customer customerToDelete;! ! public String askForDeletion(Customer customer) {! customerToDelete = customer; ! return SHOW_DELETE_CONFIRMATION; !
} !!
public String deleteCustomer(Customer customer) {! ... // call backend services! return CUSTOMER_DELETED; !
} !...!
}!
Voodoo powered
Migration GuideNo more pumped up Session
// JSF UI [email protected][email protected](“deleteCustomerController“)!public class DeleteCustomerController implements Serializable {!!
private Customer customerToDelete;!! @Inject! private Conversation conversation; ! ! public String askForDeletion(Customer customer) {! conversation.begin();! customerToDelete = customer; ! return SHOW_DELETE_CONFIRMATION; !
} !!
public String deleteCustomer(Customer customer) {! conversation.end();!
... // call backend services! return CUSTOMER_DELETED; !
} !...!
}!
Was ist, wenn schon aktiv?
Was ist, wenn nicht aktiv?
Voodoo powered
Voodoo Steps: !
‣ „Technology Independence“ ‣ „@Inject Business Objects“ ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
Views sind nach wie vor ein Problem !
‣ Injection via U-EL ‣ Injection von UI Controllern
No more Infrastructure in ViewsMigration Guide
Voodoo powered
Migration Guide
<html ...>! <h:body>! <h:form>!! Vorname: <h:inputText ! value=“#{createCustomerController.customer.firstname}"/>! Name: <h:inputText ! value=“#{createCustomerController.customer.lastname}"/> ! !! </h:form>! </h:body>!</html>!
No more Infrastructure in Views
Infrastruktur in der View
Voodoo powered
Migration Guide
<html ...>! <h:body>! <h:form>!! Vorname: <h:inputText ! value=“#{customerToCreate.firstname}"/>! Name: <h:inputText ! value=“#{customerToCreate.lastname}"/> ! !! </h:form>! </h:body>!</html>!
No more Infrastructure in Views
Fachlichkeit in der View
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! @Inject! private CustomerService customerService;!
! private Customer customer; ! !
// getter for [email protected][email protected](“customerToCreate“) !public Customer getCustomer {! return customer; !}!...!
}!!
Migration GuideNo more Infrastructure in Views
Voodoo powered
Voodoo Steps: !
‣ „Technology Independence“ ‣ @Inject Business Objects ‣ „No more EJBs for Transactions only“ ‣ „No more pumped up Sessions“ ‣ „No more Infrastructure in Views“ ‣ „No more doAll( ) Business Methods“
Enterprise ArchitectureMigration Guide
Voodoo powered
Ein Use Case kommt selten allein !
‣ Primärer Use Case - Create Customer !
‣ Sekundärer Use Case - Send Welcome Mail ‣ Sekundärer Use Case - Für Mandant X ... ‣ Sekundärer Use Case - ...
No more doAll() Business MethodsMigration Guide
Voodoo powered
CDI Events zur losen Kopplung, d.h Java EE Observer Patten inkl. ... !
‣ Event Object & Event Producer ‣ Observer Method !
‣ schichtenneutral für POJOs ‣ ggf. transaktionsgebunden ‣ synchrone Interaktion
No more doAll() Business MethodsMigration Guide
Voodoo powered
Migration Guide
Event/Message Producer
CDI Bean Manager
Observer Method
Observer Method
Observer Method
No more doAll() Business Methods
USER CREATED
interessant
ok, danke
gut zu wissen
Voodoo powered
OK, CDI Events - klingt super, aber ... !
‣Wie sieht ein solches Event aus? ‣ Und wie fange ich es ab?
!
‣ Und vor allem: Wie löse ich es aus?
No more doAll() Business MethodsMigration Guide
Voodoo powered
// JSF UI [email protected][email protected](“createCustomerController“)!public class CreateCustomerController {!! @Inject! private CustomerService customerService;!! @Inject @Created! private Event<Customer> eventSource;!
! private Customer customer; !
! @Transactional! public String createCustomer() {!
customerService.create(customer); ! eventSource.fire(customer);! return CUSTOMER_CREATED;!} !...!
}!
Migration GuideNo more doAll() Business Methods
Voodoo powered
Migration Guide
@ApplicationScoped!public class MailService implements Serializable {!! public void sendWelcomeMail(! @Observes! @Created Customer customer) { ! ! // do some work with the customer object! ! ...! }!! ...!}!
‣Wie fange ich es?
No more doAll() Business Methods
Wow! Geht da noch mehr?
Voodoo powered
Migration Guide
@ApplicationScoped!public class MailService implements Serializable {!! public void sendWelcomeMail(! @Observes @TenantId(“4711“)! @Created Customer customer) { ! ! // do some work with the customer object for tenant 4711! ! ...! }!! ...!}!
‣Wie fange ich es?
No more doAll() Business MethodsVoodoo powered
Migration Guide
@ApplicationScoped!public class MailService implements Serializable {!! // Conditional Observer Method that takes ! // - Transaction status, e.g. AFTER_SUCCESS, AFTER_FAILURE! // - Bean instance status, e.g. ALLWAYS! // into account! public void sendWelcomeMail(! @Observes( ! receive=ALLWAYS, // bean ! during=AFTER_SUCCESS // tx ! ) ! @Created Customer customer) { !
... ! }!}!!
‣ Conditional Observer
No more doAll() Business MethodsVoodoo powered
Enterprise ArchitectureVoodoo Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
Voodoo powered
Enterprise ArchitectureVoodoo Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
Voodoo powered
New School Enterprise Architecture !
‣mit CDI !
‣ typensicher ‣ schichtenneutral ‣ fachliche und technologische Injection ‣ eventgetriebene Entwicklung
FazitEnterprise Architecture
Voodoo powered
Voodoo Architecture
@mobileLarson @_openKnowledge
Lars Röwekamp | CIO New Technologies