New School Enterprise Architecture

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

Mail

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