View
545
Download
1
Category
Preview:
DESCRIPTION
Speaker: Lars Röwekamp JAX 2013 23.4.2013 | 16.15 - 17.15 Uhr Dank des aktuellen Java-EE-Stacks lassen sich heute Architekturen realisieren, von denen man zu Zeiten von J2EE nur träumen durfte. Nahezu losgelöst von technologischen und schichtenbedingten Restriktionen kommen völlig neue Patterns zum Tragen. Im Gegenzug dazu kann auf "lieb gewonnene" Workarounds - aka J2EE Pattern - verzichtet werden. Die Session gibt einen Einblick in die vielfältigen Möglichkeiten und möchte so zu neuen Denkmustern im Java-EE-Architekturdesign anregen.
Citation preview
Java
New School Enterprise ArchitectureLars Röwekamp | open knowledge GmbH
@mobileLarson@_openknowledge
„Fachlichkeit im Fokus!“
„Java EE 6 und 7 erlauben neben
Infrastructure Injection auch
Business Injection.“
Was sie mitnehmen sollten ...New School Enterprise Architecture
„Fachlichkeit im Fokus!“
„Java EE 6 und 7 erlauben neben
Infrastructure Injection auch
Business Injection.“
Was sie mitnehmen sollten ...New School Enterprise Architecture
Ok, was heißt das?
New School
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
New School
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
New School
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
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View
CreateCustomer
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View
CreateCustomer
CustService MailService
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View
CreateCustomer
CustService MailService
Customer Mail
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.RequestScoped@javax.faces.bean.ManagedBean(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...
}
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.RequestScoped@javax.faces.bean.ManagedBean(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?
New School
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
New School Enterprise Architecture
Old School Ansatz
JSF View
CreateCustomer AuthController
New School Enterprise Architecture
Old School Ansatz
JSF View
CreateCustomer
CCAgent
AuthService
AuthController
New School Enterprise Architecture
Old School Ansatz
JSF View
CreateCustomer
CCAgent
AuthService
Customer
CustService
AuthController
New School Enterprise Architecture
Old School Ansatz
JSF View
CreateCustomer
CCAgent
AuthService
MailService
Customer
CustService
AuthController
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.RequestScoped@javax.faces.bean.ManagedBean(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...
}
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.RequestScoped@javax.faces.bean.ManagedBean(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?
New School
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
New School Enterprise Architecture
Old School Ansatz
CreateCustomer
AuthService
CCAgent
AuthController
New School Enterprise Architecture
Old School Ansatz
CreateCustomer
CustFacade
AuthService
CCAgent
AuthController
TX
New School Enterprise Architecture
Old School Ansatz
CreateCustomer
CustFacade
AuthService
CCAgent
AuthController
TX
New School Enterprise Architecture
Old School Ansatz
CreateCustomer
CustFacade
AuthService
CCAgent
CustService MailService
Customer Mail
AuthController
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.RequestScoped@javax.faces.ManagedBean(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; }
...}
New School Enterprise Architecture
Old School Ansatz
// EJB Service Facade@Statelesspublic class CustomerFacade {
@EJB private CustomerService customerService
@EJBprivate MailService mailService;
// Transactional by default public void createCustomer(Customer customer, CallCenterAgent currentCallCenterAgent) {
customer.setAuditInformation(currentCallCenterAgent); customerService.create(customer); mailService.sendWelcomeMail(customer); } ...
}
New School Enterprise Architecture
Old School Ansatz
// EJB Service Facade@Statelesspublic class CustomerFacade {
@EJB private CustomerService customerService
@EJBprivate 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!
New School Enterprise Architecture
Old School Ansatz
JSF View
CreateCustomer
AuthService
CCAgent
AuthController
New School Enterprise Architecture
Old School Ansatz
JSF View
CustService
CreateCustomer
AuthService
CCAgent
AuthController
New School Enterprise Architecture
Old School Ansatz
JSF View
CustService
CreateCustomer
AuthService
CCAgent
MailService
Customer Mail
AuthController
New School
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
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View 1
DeleteCustomer
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View 1
DeleteCustomer
JSF View 2
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View 1
DeleteCustomer
CustService MailService
Customer Mail
JSF View 2
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.SessionScoped@javax.faces.bean.ManagedBean(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;
} ...
}
New School Enterprise Architecture
Old School Ansatz
// JSF UI Controller@javax.faces.bean.SessionScoped@javax.faces.bean.ManagedBean(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?
New School
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
New School Enterprise Architecture
Old School Ansatz
UI
Service
Data
JSF View
@ManagedBean (JSF)
Session EJB Session EJB
EntityManager Entity
TX
New School Enterprise Architecture
Alternativer Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
New School Enterprise Architecture
Alternativer Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
Migration Guide
New School
New School
Migration 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
New School
Migration 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
New School
// JSF UI Controller@javax.faces.bean.RequestScoped@javax.faces.bean.ManagedBean(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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
New School
Migration 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
New School
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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
New School
// 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
New School
// 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
@Inject @Current CallCenterAgent
New School
// 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
New School
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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
New School
// Customer Service EJB@Statelesspublic 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
New School
Migration 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
New School
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
New School
// Customer Service EJB @Statelesspublic 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
New School
// Customer Service EJB - no annotation required!@Statelesspublic 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
New School
// Customer Service EJB - no annotation required!@Statelesspublic 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 EJBs
New School
// Customer Service EJB - no annotation required!@Statelesspublic 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
New School
// Customer Service EJB - no annotation required!@Statelesspublic 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 EJBs
New School
@InterceptorBinding@Target({TYPE, METHOD})@Retention(RUNTIME)public @interface Transactional {
@Nonbinding public TransactionalType value()
default TransactionalType.REQUIRED;
}
Migration GuideNo more EJBs
New School
@Transactional @Interceptorpublic 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
New School
// 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
New School
// 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
New School Enterprise Architecture
UI
Service
Data
JSF View
UsecaseController
Service Service
EntityManager Entity
TX
No more EJBs
New School Enterprise Architecture
UI
Service
Data
JSF View
UsecaseController
Service Service
EntityManager Entity
TX
No more EJBs
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
New School
Migration 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
New School
Anti-Pattern „alles in die Session“
‣ RequestScoped ist leider zu kurz‣ ViewScoped irgendwie auch‣ SessionScoped aus Mangel an Alternativen
No more pumped up SessionMigration Guide
New School Migration Guide
Old School Ansatz
// JSF UI Controller@javax.enterprise.context.SessionScoped@javax.inject.Named(“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;
} ...
}
New School Migration Guide
Old School Ansatz
// JSF UI Controller@javax.context.enterprise.ConversationScoped@javax.inject.Named(“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;
} ...
}
New School
Migration 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
New School
Views sind nach wie vor ein Problem
‣ Injection via U-EL‣ Injection von UI Controllern
No more Infrastructure in ViewsMigration Guide
New School Enterprise Architecture
<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
New School Enterprise Architecture
<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
Infrastruture in der View
New School Enterprise Architecture
<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
New School Enterprise Architecture
<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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“createCustomerController“)public class CreateCustomerController {
@Inject private CustomerService customerService;
private Customer customer;
// getter for customer@javax.inject.Produces@javax.inject.Named(“customerToCreate“) public Customer getCustomer { return customer; }...
}
Migration GuideNo more Infrastructure in Views
New School
Migration 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
New School
Ein Use Case kommt selten allein
‣ Primärer Use Case - Create Customer
‣ Sekundärer Use Case - Send Welcome Mail‣ Sekundärer Use Case - ...‣ Sekundärer Use Case - ...
No more doAll() Business MethodsMigration Guide
New School
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
New School Migration Guide
Event/Message
Producer
CDI Bean Manager
Observer Method
Observer Method
Observer Method
No more doAll() Business Methods
New School Migration Guide
Event/Message
Producer
CDI Bean Manager
Observer Method
Observer Method
Observer Method
No more doAll() Business Methods
USER CREATED
New School 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
New School
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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
New School
// JSF UI Controller@javax.enterprise.context.RequestScoped@javax.inject.Named(“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
Wow! Geht da noch mehr?
New School Enterprise Architecture
@ApplicationScopedpublic 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
New School Enterprise Architecture
@ApplicationScopedpublic 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 Methods
New School Enterprise Architecture
Alternativer Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
New School Enterprise Architecture
Alternativer Ansatz
UI
Domain
JSF View
UseCaseController
Business Object
Business Object
Business Object
TX
New School
New School Enterprise Architecture
‣mit CDI
‣ typensicher ‣schichtenneutral‣ fachliche und technologische Injection ‣ eventgetriebene Entwicklung
FazitEnterprise Architecture
Java
New School Enterprise ArchitectureLars Röwekamp | open knowledge GmbH
@mobileLarson@_openknowledge
Recommended