129
Extend Java EE with CDI Antoine Sabot-Durand · Antonio Goncalves

Extending Java EE with CDI and JBoss Forge

Embed Size (px)

Citation preview

Page 1: Extending Java EE with CDI and JBoss Forge

ExtendJavaEEwithCDI

AntoineSabot-Durand·AntonioGoncalves

Page 2: Extending Java EE with CDI and JBoss Forge

AntoineSabot-Durand

RedHatCDIspeclead@antoine_sdnext-presso.comgithub.com/antoinesd

Page 3: Extending Java EE with CDI and JBoss Forge

AntonioGoncalves

JavaChampionContractordevelopperantoniogoncalves.org@agoncalgithub.com/agoncal

Page 4: Extending Java EE with CDI and JBoss Forge

Agenda

MeetExpensEEsMeetCDIBasicDIProducersInterceptorsQualifiersProgrammaticLookupContextsEventsExtensionsConclusion

Page 5: Extending Java EE with CDI and JBoss Forge

ExpensesmadeEEsy

MeetExpensEEs

Page 6: Extending Java EE with CDI and JBoss Forge

WewereaskedtobuildthisappAwebapptomanageexpensesBasedonJavaEE7CDI1.2JPA2.1JSF2.2JAX-RS2.0Abletointegratelegacylibs

Page 7: Extending Java EE with CDI and JBoss Forge

Storyboard-HomeScreen

Page 8: Extending Java EE with CDI and JBoss Forge

Storyboard-LoginScreen

Page 9: Extending Java EE with CDI and JBoss Forge

Storyboard-NewUserScreen

Page 10: Extending Java EE with CDI and JBoss Forge

Storyboard-LoggedIn

Page 11: Extending Java EE with CDI and JBoss Forge

Storyboard-Profile

Page 12: Extending Java EE with CDI and JBoss Forge

Storyboard-ExpenseDetail

Page 13: Extending Java EE with CDI and JBoss Forge

Storyboard-ExpenseConfirm

Page 14: Extending Java EE with CDI and JBoss Forge

Storyboard-ViewExpenses

Page 15: Extending Java EE with CDI and JBoss Forge

Architecture-ModelUser

String loginString passwordString nameString emailUserRole role

Reimbursement

Date dateSet<Expense> expensesCurrency currencyUser userConference conference

Expense

descriptionDate dateFloat amountExpenseType expenseTypeprivate Currency currency

Conference

String nameDate dateString countryString city

1

*

1 *

1

*

Page 16: Extending Java EE with CDI and JBoss Forge

Let’sForgeExpensEEs!

Page 17: Extending Java EE with CDI and JBoss Forge

JBossForge

Forge

1. Generation&Scaffoldingtool2. Shellcommands&IDEIntegration3. Getsyoustartquickly4. Takescareofintegration5. Pluginbased6. JavaEE…Butanythingelsereally7. Moreinfoonforge.jboss.org/

Page 18: Extending Java EE with CDI and JBoss Forge

Backtodemo RunJBossForge

CreateJPAEntities

ScaffoldJSFCRUDpages

ScaffoldRESTEndpoint

RunForgescript

Page 19: Extending Java EE with CDI and JBoss Forge

ArchitectureForgehtml

web rest

model

ConferenceCRUDExpenseCRUD ReimbursementCRUD UserCRUD

ConferenceBeanExpenseBean ReimbursementBean UserBean ConferenceEndpoint

ConferenceExpenseService Reimbursement User

useuse use use

useuseuse use use

Page 20: Extending Java EE with CDI and JBoss Forge

NotFinishedYet

1. OnlyaCRUDapp2. No"Createexpenses"Wizard3. NoLogin/logout4. Primefaces5. JavaEE6insteadofJavaEE76. JTA1.2@Transactional7. JPA2.1InsertdatainDB8. NotinfullCDIprogrammingmodel!

Page 21: Extending Java EE with CDI and JBoss Forge

Backtodemo

Refactortheapp

Addaservicelayer

AddJavaEE7dependencies

LessEJBMoreCDI

WebjarforTwitterBootstrap

2hourslater…

Page 22: Extending Java EE with CDI and JBoss Forge

NewArchitecturehtml

web rest

service

model

ConferenceCRUDExpenseCRUD ReimbursementCRUD UserCRUD

ConferenceBeanExpenseBean ReimbursementBean UserBean ConferenceEndpoint

ConferenceServiceExpenseService ReimbursementService UserService

ConferenceExpense Reimbursement User

useuse use use

@Inject@Inject@Inject @Inject @Inject

useuse use use

Page 23: Extending Java EE with CDI and JBoss Forge

ContextsandDependencyInjection

MeetCDI

Page 24: Extending Java EE with CDI and JBoss Forge

WhatisCDI?AJavaEEspec.ASL2(evenTCK)LaunchedinJavaEE62releasessincelaunch1.2islast(JavaEE7)2.0onitsway2majorimpl.JBossWeld(RI)ApacheOpenWebBeans

Page 25: Extending Java EE with CDI and JBoss Forge

What’sincluded?CDIProvides:

1. Apowerfulprogrammingmodel2. DifferentLifecyclesforstateful

objects3. ATypesafeDImechanism4. Theabilitytodecorateinjected

objects5. Theabilitytointerceptmethods6. Aneventnotificationmodel7. ASPIallowingportableextensionstointegrate3rdpartytech

Page 26: Extending Java EE with CDI and JBoss Forge

“CDIexplainedtoyourboss

CDIbringsapowerfulandmodernprogrammingmodelthatstandardizesgoodpractices.

CDIprovidesaconsistentandseamlesswaytointegrate3rdpartyframeworkstothismodel.

Onceadopted,CDIwillbecometheinvisiblebackboneofourprojects.

Page 27: Extending Java EE with CDI and JBoss Forge

Onecontainertorulethemall ThecontaineristheheartofCDI

ThecontainerchecksallpossibleCDIcodeatboottime

Thecontainermanagesyourcomponentslifecycleandservices

Yet,you’llneverseeit(exceptinadvanceddevelopment)

Containerisyourapplication’sinvisibleconductor

Page 28: Extending Java EE with CDI and JBoss Forge

@Inject

Page 29: Extending Java EE with CDI and JBoss Forge

AlmostEverythingisabean

Duringboottime,thecontainerscanseachclasstocheckifitmeetstheconditionstobeabean

Theseconditionsareverylooseso,mostpojoclassesarebeans

public class HelloService { public String hello() { return "Hello World!"; }}

HelloService isaconcreteclasswithadefaultconstructor,thereforeit’sabean

1

1

Page 30: Extending Java EE with CDI and JBoss Forge

Injectioninbeanfield Abeancaninjectotherbeansorbeinjectedintootherbeans

public class MyBean { @Inject private HelloService service;

public void displayHello() { display(service.hello(); }}

@Inject annotationdefinesaninjectionpoint(hereafield)

Thecontainerlooksaforthebeantoinjectbyitstype(here HelloService )

12

1

2

Page 31: Extending Java EE with CDI and JBoss Forge

Injectioninbeanconstructor

Tobecomeabeanaclassmusthaveaconstructorwithnoparametersoraconstructorannotated @Inject

public class MyBean {

private HelloService service;

@Inject private MyBean(HelloService service) { this.service = service; }}

Onlyoneconstructorcanbeannotatedwith @Inject

Page 32: Extending Java EE with CDI and JBoss Forge

Injectioninamethod Suchmethodiscalledinitializermethods

public class MyBean {

private HelloService service;

@Inject public void initService(HelloService service) { this.service = service; }}

allinitializermethodsarecalledatbeaninstantiation

Page 33: Extending Java EE with CDI and JBoss Forge

TherecouldbeonlyoneEachinjectionpointischeckedatboottime:

Ifnobeaniseligibleforit,theinjectionpointisunsatisfied

Ifmultiplebeansareeligibleforit,theinjectionpointisambiguous

Inbothcasea DeploymentException isthrownbythecontainer

Page 34: Extending Java EE with CDI and JBoss Forge

Backtodemo

InjectaLoggerinto UserService

Logamessagein persist method

Page 35: Extending Java EE with CDI and JBoss Forge

Whenyoudon’townyourbean’sclass,use

Producers

Page 36: Extending Java EE with CDI and JBoss Forge

Whatisaproducer?Awaytodeclareabean…

…fromafieldoramethod…

…foraclassyoudon’town…

…oranonCDIclass.

Page 37: Extending Java EE with CDI and JBoss Forge

DeclaringaProducerpublic class ProducingBean { @Produces private List<Integer> mapInt = new ArrayList<>();

@Produces @French public List<String> FrenchListStrProducer() { List<String> res = Arrays.asList("bonjour"); return res; }}

ProducersshouldbedeclaredinaBeanclass

It’safieldoramethodannotatedwith @Produces (staticmethodssupported)

Producerscanhavequalifiers

valueoffieldormethodreturnedvalueisthebeaninstance

12

23

4

1

2

3

4

Page 38: Extending Java EE with CDI and JBoss Forge

Producersareanotherkindofbean theycanhavequalifierslikeanyotherbean

producermethod(orfield)iscalledtocreatethebeaninstance

public class MyBean {

@Inject @French private List<String> frenchListStrBean;

@Inject public MyBean(List<Integer> initValues) { ... }}

Page 39: Extending Java EE with CDI and JBoss Forge

DisposersareProducer’shousekeeping Disposerscanfreeresourceswhenproducedbeanisdestroyed

public class ProducingBean {

@Produces public MyNonCDIClass myProducer() { return new MyNonCdiClass(); }

public void releaseMyInstance(@Disposes MyNonCdiClass inst) { inst.clean(); }}

Willbecalledatthebeaninstanceendoflife

1

1

Page 40: Extending Java EE with CDI and JBoss Forge

Producermethodscanhaveparameters Parameterswillbeinjectedbythecontaineratinstantiationtime

Theyshouldhavematchingbeansotherwisedeploymentfails

public class ProducingBean {

@Produces public MyNonCDIClass listStrProducer(MyBean bean) { ... }}

Thecontainerresolves MyBean andpassesittotheproducerwhenaninstanceofthebeanisrequested

1

1

Page 41: Extending Java EE with CDI and JBoss Forge

Backtodemo

Theclass LoggerProducer producesaLogger

Injectingaloggerinservicedoesn’tchange

Page 42: Extending Java EE with CDI and JBoss Forge

AccessingInjectionPointmetadata ThecontainercanprovidemetadataabouttheInjectionPoint

public class ProducingBean {

@Produces public Logger produceLog(InjectionPoint injectionPoint) { return Logger.getLogger(injectionPoint.getMember() .getDeclaringClass().getName()); }}

InjectionPoint isaSPIinterface.Thecontainercaninjectittogiveinfoabouttheinjectionpoint

1

1

Page 43: Extending Java EE with CDI and JBoss Forge

Backtodemo

Add InjectionPoint APItotheproducer

Injectingaloggerinservicedoesn’tchange

Page 44: Extending Java EE with CDI and JBoss Forge

InterceptorsandDecorators

Page 45: Extending Java EE with CDI and JBoss Forge

InterceptorsvsDecorators TheyarebothAspectOrientedProgrammingtools

Interceptorsaretechnicaloriented:transaction,security,logging

Interceptorsareboundtoanybeanorbeanmethod

Decoratorsarebusinessoriented:changethebehaviourofabean

Decoratorsareboundtoabeantype

Page 46: Extending Java EE with CDI and JBoss Forge

Interceptors Interceptorsaredefinedintheirownspecification

Usershouldcreateanannotationasaninterceptorbinding

Interceptorclassmustbeboundtoaninterceptorbinding

Interceptorclasscontainsinterceptingmethodswhichareboundtolifecyclephaseofinterceptedbean

Interceptorbindingisaddedtointerceptedbeanormethod

Page 47: Extending Java EE with CDI and JBoss Forge

Interceptorbindingexample Aninterceptorbindingisannotationusedintwodifferentplaces

Ontheinterceptorandontheinterceptedelementtolinkthem

@InterceptorBinding @Target({METHOD, TYPE})@Retention(RUNTIME)public @interface Loggable {}

Thisannotationcomesfrominterceptorspecification.Itmakes @Loggable aninterceptorbinding

1

1

Page 48: Extending Java EE with CDI and JBoss Forge

Interceptorexample@Interceptor

@Loggable

@Priority(Interceptor.Priority.APPLICATION) public class LogInterceptor {

@AroundInvoke public Object log(InvocationContext ic) throws Exception { System.out.println("Entering " + ic.getMethod().getName()); try { return ic.proceed(); } finally { System.out.println("Exiting " + ic.getMethod().getName()); } }}

Wemaketheclassaninterceptor( @Interceptor comesfromInterceptorspec)

Webindthisinterceptortothe @Loggable interceptorbinding

Weactivateandgiveaprioritytotheinterceptor(canbedonein beans.xml configfileaswell)

Thisinterceptingmethodwillbeinvokedinsteadoftheinterceptedone.

12

3

4

1

2

3

4

Page 49: Extending Java EE with CDI and JBoss Forge

InterceptorUsage@Loggable public class MyBean { ... }

public class MyOtherBean {

@Loggable public String hello() { ... }

}

Allbean’smethodwillbeintercepted

Thismethodwillbeintercepted

1

2

1

2

Page 50: Extending Java EE with CDI and JBoss Forge

Decorators Tobedecorated,abeanshouldimplementaninterface

Thedecoratorhastoimplementthesameinterface

Itisdeclaredwith @Decorator annotation

Itcanbeanabstractclass(letsyouchoosemethodstodecorate)

Itinjectsthedecoratedbeanwith @Delegate annotation

Page 51: Extending Java EE with CDI and JBoss Forge

DecoratorExample@Decorator

@Priority(Interceptor.Priority.APPLICATION)

public abstract class HelloDecorator implements HelloService {

@Inject @Delegate HelloService service;

public String hello() { return service.hello() + "-decorated"; }}

Declaresthattheclassisadecorator

Activatesandgivesaprioritytothedecorator(couldbedonevia beans.xml file)

Decoratorscanbeabstractandshouldsharethesameinterfacethandecoratedbeans

Decoratedbeanisannotatedwith @Delegate (otherbeanscouldbeinjectedindecorator)

Decoratingmethodiscalledinsteadofdecoratedbeanmethod.Delegatecanbeusedinit.

12

3

4

5

1

2

3

4

5

Page 52: Extending Java EE with CDI and JBoss Forge

Backtodemo Createa @Loggable interceptorbinding

Createa LoggingInterceptor

Add LoggingInterceptor toeachservice

Enableinterceptorinthe beans.xml

Page 53: Extending Java EE with CDI and JBoss Forge

Solvingambiguouscaseswith

Qualifiers

Page 54: Extending Java EE with CDI and JBoss Forge

Whenaninjectionpointresolvestomultiplebeans…public class MyBean { @Inject HelloService service;}

public interface HelloService { public String hello();}

public class FrenchHelloService implements HelloService { public String hello() { return "Bonjour tout le monde!"; }}

public class EnglishHelloService implements HelloService { public String hello() { return "Hello World!"; }}

deploymentfailswithan Ambiguous dependencies error.

Page 55: Extending Java EE with CDI and JBoss Forge

ThesolutionistocreateQualifiers…@Qualifier@Retention(RUNTIME)@Target({FIELD, TYPE, METHOD, PARAMETER})public @interface French {}

@Qualifier@Retention(RUNTIME)@Target({FIELD, TYPE, METHOD, PARAMETER})public @interface English {}

Qualifiersareannotationsannotatedwith @Qualifier

Page 56: Extending Java EE with CDI and JBoss Forge

toqualifybeanssharingthesametype…

@Frenchpublic class FrenchHelloService implements HelloService { public String hello() { return "Bonjour tout le monde!"; }}

@Englishpublic class EnglishHelloService implements HelloService { public String hello() { return "Hello World!"; }}

Page 57: Extending Java EE with CDI and JBoss Forge

anddistinguishthematinjectionpoints.

public class MyBean { @Inject @French HelloService serviceFr;

@Inject @English HelloService serviceEn; }

Qualifiersaretypesenhancinginjection,yetkeepingitstrongtyped

Page 58: Extending Java EE with CDI and JBoss Forge

Qualifierscanhavemembers@Qualifier@Retention(RUNTIME)@Target({FIELD, TYPE, METHOD, PARAMETER})public @interface Language {

LangChoice value();

@Nonbinding String description() default "";

public enum LangChoice { FRENCH, ENGLISH }}

@Nonbinding member’svalueisn’tusedinbeanresolutionmechanism

1

1

Page 59: Extending Java EE with CDI and JBoss Forge

Bindingmemberslimitthenumberofannotationstoaddtoyourcode

@Language(FRENCH)public class FrenchHelloService implements HelloService { public String hello() { return "Bonjour tout le monde!"; }}

@Language(ENGLISH)public class EnglishHelloService implements HelloService { public String hello() { return "Hello World!"; }}

public class MyBean { @Inject @Language(value = FRENCH, description = "ici on parle français") HelloService serviceFr;

@Inject @Language(value = ENGLISH, description = "english spoken here") HelloService serviceEn;}

Page 60: Extending Java EE with CDI and JBoss Forge

Multiplequalifiers Abeancanhavemultiplequalifiers

@Language(FRENCH) @Console public class FrenchHelloService implements HelloService { public String hello() { return "Bonjour tout le monde!"; }}

public class MyBean { @Inject @Language(FRENCH) @Console HelloService serviceFr;}

@Console isaqualifier

1

1

Page 61: Extending Java EE with CDI and JBoss Forge

Multiplequalifiers

Injectionpointcanhaveanonemptysubsetofthebean’squalifiers

@Language(FRENCH) @Consolepublic class FrenchHelloService implements HelloService { public String hello() { return "Bonjour tout le monde!"; }}

public class MyBean { @Inject @Console HelloService serviceFr;}

Page 62: Extending Java EE with CDI and JBoss Forge

Multiplequalifiers Injectionpointcan’thaveasupersetofbean’squalifier

@Language(FRENCH) @Consolepublic class FrenchHelloService implements HelloService { public String hello() { return "Bonjour tout le monde!"; }}

public class MyBean { @Inject @Language(FRENCH) @Console @Language(CANADIAN) HelloService serviceFr;}

Unsatisfiedinjectionpoint:deploymentfails

1

1

Page 63: Extending Java EE with CDI and JBoss Forge

Built-inqualifiers

@Named setbeannameforweaktypedenvironment(EL,Javascript)

@Default addedtobeanswithoutqualifierorhavingonly@Named

@Any addedtoallbeansforprogrammaticlookupanddecorators

@Intercepted & @Decorated toinjectinterceptedbeaninaninterceptor/Decorator

@Initialized toqualifyeventswhenacontextisstarted

Page 64: Extending Java EE with CDI and JBoss Forge

Examplespublic class MyBean { ... } @Namedpublic class MyBean2 { ... }

@Named @Language(FRENCH) public class MyBean2 { @Inject MyBean2 bean;}

thisbeanhas @Default and @Any qualifiers

thisbeanhas @Default , @Named and @Any qualifiers

thisbeanhas @Language(FRENCH) , @Named and @Any qualifiers

thisinjectionpointhas @Default qualifier

1

2

3

4

1

2

3

4

Page 65: Extending Java EE with CDI and JBoss Forge

BeanTypes Abeanhasasetoftypesdependingonitsdefinition

Beantypessetforamanagedbeancontainsthebeanclass,everysuperclassandallinterfacesitimplementsdirectlyorindirectly.

Beantypescanberestrictedbyusing @Typed annotation( Objectisalwaysintheset)

Page 66: Extending Java EE with CDI and JBoss Forge

BeantypesExamplepublic interface HelloService extends Hello { ... }

public class MyBean { @Produces

public HelloService prodHelloService() { ... } }

public class FrHelloService extends GenericService<String> implements HelloService { ... }

@Typed({HelloService.class})

public class FrHelloService extends GenericService<String> implements HelloService { ... }

class MyBean and Object

HelloService , Hello and Object

FrHelloService , GenericService<String> , HelloService , Hello and Object

HelloService and Object

1

2

3

4

1

2

3

4

Page 67: Extending Java EE with CDI and JBoss Forge

Parameterizedtypescount Parameterizedtypesinformationiskept(i.e.notypeerasure)

public class MyBean {

@Inject Service<User> userService;

@Inject Service<Staff> staffService; }

Injectionpointsabovecanbesatisfiedwithoutambiguity

Page 68: Extending Java EE with CDI and JBoss Forge

PerformingTypesafeResolution Whenresolvingabeantobeinjectedtoaninjectionpoint…

…thecontainerconsidersbeantypeandqualifiers.

Ifthebeanhasabeantypethatmatchesinjectionpointtype…

…andthebeanhasallthequalifiersoftheinjectionpoint…

…thebeanisassignabletotheinjectionpoint.

Page 69: Extending Java EE with CDI and JBoss Forge

Backtodemo Createa @Clear and @Encrypted qualifiers

Createa DigestPassword interface

Twoimplementations ClearPassword and EncryptPassword

Injectencryptedpassworddigestinto AccountBean andUserService

Page 70: Extending Java EE with CDI and JBoss Forge

Resolvingbeansatruntime

ProgrammaticLookup

Page 71: Extending Java EE with CDI and JBoss Forge

MeetInstance interface Instance interfaceletsperformtypesaferesolutionatruntime

public class MyBean {

@Inject Instance<HelloService> service;

public void displayHello() { display(service.get().hello()); }}

Instance<T> injectionpointsarealwayssatisfiedandneverfailatdeploymenttime

with Instance<T> youcontrolwhenbeanainstanceisrequestedwiththe get() method

1

2

1

2

Page 72: Extending Java EE with CDI and JBoss Forge

Checkbeanexistenceatruntime Instance<T> containsmethodstotestbeanresolution

public class MyBean {

@Inject Instance<HelloService> service;

public void displayHello() { if (!(service.isUnsatisfied() || service.isAmbiguous())) { display(service.get().hello()); } }}

iftouskipthetest get() maythrowanexception

1

1

Page 73: Extending Java EE with CDI and JBoss Forge

Loopingonallbeansinthe Instance

Instance<T> isiterable

It’swhereweusethe @Any qualifierpresentonallbeans

public class MyBean {

@Inject @Any Instance<HelloService> services;

public void displayHello() { for (HelloService service : services) { display(service.hello()); } }}

Page 74: Extending Java EE with CDI and JBoss Forge

Selectabeanbyitsqualifier

AnnotationLiteral isahelperclasstocreateanannotationinstance

public class MyBean {

@Inject @Any Instance<HelloService> services;

public void displayHello() { display( services.select(new AnnotationLiteral()<French> {}).get()); }}

select() alsoacceptsatype.

youcanuse TypeLiteral tocreateinstancesofparameterizedtypes

1

1

Page 75: Extending Java EE with CDI and JBoss Forge

Backtodemo Loopthroughall DigestPassword

Thanksto @Any

Useeither @Encrypted or @Clear

Page 76: Extending Java EE with CDI and JBoss Forge

Beanslifeanddeath

Contexts

Page 77: Extending Java EE with CDI and JBoss Forge

Bean,ScopeandContexts AllBeanshaveascopedefinedbyanannotation

Eachscopeisassociatedtoacontextobject

Soeachbeanisboundtoacontext

Thecontextisinchargeofcreatingbeaninstances

TheContainerisinchargeofcreatinganddestroyingcontexts

Page 78: Extending Java EE with CDI and JBoss Forge

Availablescopes

CDIprovidesthefollowingbuilt-inscopes(andassociatedcontexts):

@Dependent (default)beanhasthesamescopethanitsinjector @ApplicationScoped instanceislinkedtoapplicationlifecycle @SessionScoped instanceislinkedtohttpsessionlifecycle @RequestScoped instanceislikedtohttprequestlifecycle @ConversationScoped lifecyclemanuallycontrolledwithinsession

Instanceiscreatedatfirstrequestanddestroyedwithitsboundcontext

CDISPIallowsthirdpartytocreatetheircustomcontexts

Page 79: Extending Java EE with CDI and JBoss Forge

Examplespublic class BaseHelloService implements HelloService { ... }

@RequestScoped public class RequestService { @Inject HelloService service;}

@ApplicationScoped public class ApplicationService { @Inject RequestService service; }

Beanhasdefaultscope @Dependent ,instancesarecreatedforeachinjection

Beanis @RequestScoped .Instanceiscreatedbyrequestcontextanddestroyedwithrequestcontext

Beanis @ApplicationScoped .Instanceiscreatedbyapplicationcontextandwillliveduringallapplication

Noproblemtoinjectbeanfromanotherscope:CDIwillprovidetherightbean

1

2

3

4

1

2

3

4

Page 80: Extending Java EE with CDI and JBoss Forge

Goodtoknow

instancesarecreatedwhenfirstaccessednotwiththeircontext

Abeaninstanceisasingletoninitscontext

WithSPIyoucanmanuallydestroyaninstanceinacontext

Acontextcanbeinactivewithoutbeingdestroyed

Requestcontextismorethanamappingto ServletRequest lifecycle

Page 81: Extending Java EE with CDI and JBoss Forge

Moreon@ConversationScoped Acontextwhoselifecycleiscontrolledbythedev

Conversationistransientorlongrunning

It’spromotedtolongrunningwith Conversation built-inbean…

…bycalling begin() method…

…andterminatedwith end() .

TherecanbemultipleconversationsinoneHttpSession

Conversation id isusedtoretrievetheactiveconversation

Page 82: Extending Java EE with CDI and JBoss Forge

Example@ConversationScopedpublic class WizardBean {

@Inject Conversation conversation;

public startWizard() { ... conversation.begin() ... }

public endWizard() { ... conversation.end() ... }}

Page 83: Extending Java EE with CDI and JBoss Forge

Backtodemo Wizardtocreatenewexpenses

Useof @ConversationScoped

JSFdealswith cid

Page 84: Extending Java EE with CDI and JBoss Forge

Contextsarenotalwaysconvenient

Lifecyclemagicmanagementcanlimityou

Beaninstancesaredestroyedonlywhencontextends

Andyoumightwanttogetridofinstancebutkeepthecontext

CDI1.1addedaprogrammaticwaytodestroyaninstance

Page 85: Extending Java EE with CDI and JBoss Forge

Example-Logoutandsessioninvalidation@Inject FacesContext facesContext;

public String logout(){ try{ facesContext.getExternalContext().invalidateSession(); return "success?faces-redirect=true"; } catch(Exception e){ return "error"; }}

redirectisimportanttoendcurrentrequestandkillthesessioneffectively

wemightwanttokeepthecurrentsessionandlogoutuser

notagoodpracticetocallUIlayerfromservicetoperformbusiness

1

1

Page 86: Extending Java EE with CDI and JBoss Forge

Example-DologoutinaCDIway@Named@SessionScopedpublic class AccountBean implements Serializable {

@Inject private Instance<AccountBean> myInstance;

public String doLogout() { myInstance.destroy(myInstance.get()); return "/index"; }

SinceCDI1.1, Instance providesa destroy() methodtoremoveaninstancefromitscontext

1

1

Page 87: Extending Java EE with CDI and JBoss Forge

Backtodemo

AccountBean injectsareferencetoitself

AccountBean destroysitforlogout

Page 88: Extending Java EE with CDI and JBoss Forge

Alternatives&Stereotypes

Page 89: Extending Java EE with CDI and JBoss Forge

Alternatives

Analternativeisabeanthatmustbeexplicitlyselected

Whenselecteditsuperseedsbeanssharingthesametype

AconvenientwaytocreateMockorspecificimplementation

Analternativecanbeactivatedin beans.xml orwith @Priority

Page 90: Extending Java EE with CDI and JBoss Forge

AlternativeExamplepublic SapService implements ErpService { }

@Alternativepublic MockSapService implements ErpService { }

@ApplicationScopedpublic OrderService { @Inject ErpService service; }

Aservicedoingheavyorcostlyoperation

Canbemockedwithanalternative

Beansinjectingtheservicehavenothingtodo.Alternativewillreplacetheoriginalbeanifselected

1

2

3

1

2

3

Page 91: Extending Java EE with CDI and JBoss Forge

SelectingtheAlternative

With @Priority annotaion(forthewholeapp)

@Alternative@Priority(Interceptor.Priority.APPLICATION) public MockSapService implements ErpService {}

With beans.xml file(forthecurrentmodule)

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"> <alternatives> <class>com.acme.MockSapService</class> </alternatives></beans>

1

Page 92: Extending Java EE with CDI and JBoss Forge

Stereotypes

Stereotypesarealiasforannotations

AnhelptoavoidannotationsHell

Anotherwaytoenablealterntives

Page 93: Extending Java EE with CDI and JBoss Forge

Stereotypes

wehavealotofbeanwith @Conversation and @Named

wecancreateastereotypegatheringboth

@Stereotype @Named @ConversationScoped @Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})@Documentedpublic @interface Wizard {}

WearedelcaringaStereotype

Alltheannotationswewanttoputinthestereotype

12

2

1

2

Page 94: Extending Java EE with CDI and JBoss Forge

UsingStereotypes

Wecanusethestereotypebyreplacing

@Named @ConversationScopedpublic class ConferenceBean implements Serializable {...}

by…

@Wizardpublic class ConferenceBean implements Serializable {...}

Page 95: Extending Java EE with CDI and JBoss Forge

Moredecouplingwith

Events

Page 96: Extending Java EE with CDI and JBoss Forge

Eventsinactionpublic class FirstBean {

@Inject Event<Post> postEvent;

public void saveNewPost(Post myPost) {

postEvent.fire(myPost); }}

public class SecondBean {

public void listenPost(@Observes Post post) { System.out.println("Received : " + evt.message()); }}

Event<T> isinjectedatthefiringside. T istheeventpayloadtype(heremy Post class)

Whenneeded,wefiretheeventwithourinstanceof T (herethe Post objecttosave)

Attheconsumingside,wedefineanobserverforagivenpayloadtypewith @Observes annotation.Ifobservedtypematchfiredeventtype,theobserveriscalled.

1

2

3

1

2

3

Page 97: Extending Java EE with CDI and JBoss Forge

Observerresolutionmimicstypesaferesolution(inalooserway)public class FirstBean { @Inject Event<Post> postEvent;

public void saveNewPost(Post myPost) { postEvent.select(new AnnotationLiteral()<French> {}).fire(myPost); }}

public class SecondBean { public void listenFrPost(@Observes @French Post post) {} public void listenPost(@Observes Post post) {} public void listenObject(@Observes Object obj) {} public void listenEnPost(@Observes @English Post post) {} }

Theseobserverswillbetriggered(emptysubsetisacceptedforqualifierswhenresolvingobservers)

Thisobserverwon’tbetriggered

11

12

1

2

Page 98: Extending Java EE with CDI and JBoss Forge

Hookingoncontextlifecyclewitheventspublic class SecondBean { public void beginRequest(@Observes @Initialized(RequestScoped.class) ServletRequest req) {}

public void endRequest(@Observes @Destroyed(RequestScoped.class) ServletRequest req) {}

public void beginSession(@Observes @Initialized(SessionScoped.class) HttpSession session) {}

public void endSession(@Observes @Destroyed(SessionScoped.class) HttpSession session) {}

public void beginApplication(@Observes @Initialized(ApplicationScoped.class) ServlerContext ctx) {}

public void endApplication(@Observes @Destroyed(ApplicationScoped.class) ServlerContext ctx) {}}

Observermustbedefinedinabean

Observerresolutionmaytriggerbeaninstancecreation.

Soobserversaboveareanicewaytoinitailizebeanwithitscontext

Page 99: Extending Java EE with CDI and JBoss Forge

Backtodemo BankingService istheobserver

ReimburseService firestheevent

Theeventistypedto Reimbursement

Page 100: Extending Java EE with CDI and JBoss Forge

IntroducingCDIPortableExtensions

Page 101: Extending Java EE with CDI and JBoss Forge

Portableextensions

OneofthemostpowerfulfeatureoftheCDIspecification

Notreallypopularized,partlydueto:

1. Theirhighlevelofabstraction2. ThegoodknowledgeonBasicCDIandSPI3. Lackofinformation(CDIisoftenreducedtoabasicDIsolution)

Page 102: Extending Java EE with CDI and JBoss Forge

Extensions,whatfor?

Tointegrate3rdpartylibraries,frameworksorlegacycomponents

Tochangeexistingconfigurationorbehavior

ToextendCDIandJavaEE

Thankstothem,JavaEEcanevolvebetweenmajorreleases

Page 103: Extending Java EE with CDI and JBoss Forge

Extensions,how?

ObservingSPIeventsatboottimerelatedtothebeanmanagerlifecycle

Checkingwhatmeta-dataarebeingcreated

Modifyingthesemeta-dataorcreatingnewones

Page 104: Extending Java EE with CDI and JBoss Forge

Moreconcretely

Serviceprovideroftheservicejavax.enterprise.inject.spi.Extension declaredinMETA-INF/services

Justputthefullyqualifiednameofyourextensionclassinthisfile

import javax.enterprise.event.Observes;import javax.enterprise.inject.spi.Extension;

public class CdiExtension implements Extension {

void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) { } //...

void afterDeploymentValidation(@Observes AfterDeploymentValidation adv) { }}

Page 105: Extending Java EE with CDI and JBoss Forge

Internal Step Happen Once Loop on Elements

Beanmanagerlifecycle

DeploymentStart

BeforeBean

DiscoveryScan

Archive

ProcessAnnotated

Type

AfterType

Discovery

BeanEligibility

Check

ProcessInjection

Point

ProcessInjectionTarget

ProcessBean

Attributes

ProcessBean

ProcessProducer

ProcessObserverMethod

AfterBean

Discovery

AfterDeploymentValidation

ApplicationRunning

BeforeShutdown

UndeployApplication

Page 106: Extending Java EE with CDI and JBoss Forge

Example:IgnoringJPAentities

ThefollowingextensionpreventsCDItomanageentities

Thisisacommonlyadmittedgoodpractice

public class VetoEntity implements Extension {

void vetoEntity(@Observes @WithAnnotations(Entity.class) ProcessAnnotatedType<?> pat) { pat.veto(); }}

Page 107: Extending Java EE with CDI and JBoss Forge

ExtensionsarelaunchedduringbootstrapandarebasedonCDIevents

Oncetheapplicationisbootstrapped,theBeanManagerisinread-onlymode(noruntimebeanregistration)

Youonlyhaveto@Observes built-inCDIeventstocreateyourextensions

Remember

Page 108: Extending Java EE with CDI and JBoss Forge

UnderstandingSPItobuildCDIextensions

Page 109: Extending Java EE with CDI and JBoss Forge

SPIcanbesplitin4parts

Page 110: Extending Java EE with CDI and JBoss Forge

SPIcanbesplitin4parts

Typemeta-model

Page 111: Extending Java EE with CDI and JBoss Forge

SPIcanbesplitin4parts

CDImeta-model

Page 112: Extending Java EE with CDI and JBoss Forge

SPIcanbesplitin4parts

CDIentrypoints

Page 113: Extending Java EE with CDI and JBoss Forge

SPIcanbesplitin4parts

SPIdedicatedtoextensions

Page 114: Extending Java EE with CDI and JBoss Forge

Whyhavingatypemeta-model?

Because @Annotations areconfiguration

buttheyarealsoread-only

Sotoconfigureweneedamutablemeta-model…

…forannotatedtypes

Page 115: Extending Java EE with CDI and JBoss Forge

SPIfortypemeta-model

Annotated

Type getBaseType()Set<Type> getTypeClosure()<T extends Annotation> getAnnotation(Class<T>)Set<Annotation> getAnnotations()boolean isAnnotationPresent(Class<? extends Annotation>)

AnnotatedMemberX

Member getJavaMember()boolean isStatic()AnnotatedType<X> getDeclaringType()

AnnotatedParameterX

int getPosition()AnnotatedCallable<X> getDeclaringCallable()

AnnotatedTypeX

Class<X> getJavaClass()Set<AnnotatedConstructor<X>> getConstructors()Set<AnnotatedMethod<? super X>> getMethods()Set<AnnotatedField<? super X>> getFields()

AnnotatedCallableX

List<AnnotatedParameter<X>> getParameters()

AnnotatedFieldX

Field getJavaMember()

AnnotatedConstructorX

Constructor<X> getJavaMember()

AnnotatedMethodX

Method getJavaMember()

Page 116: Extending Java EE with CDI and JBoss Forge

SPIdedicatedtoCDImeta-model

BeanAttributesT

Set<Type> getTypes()Set<Annotation> getQualifiers()Class<? extends Annotation> getScope()String getName()Set<Class<? extends Annotation>> getStereotypes()boolean isAlternative()

BeanT

Class<?> getBeanClass()Set<InjectionPoint> getInjectionPoints()boolean isNullable()

InterceptorT

Set<Annotation> getInterceptorBindings()boolean intercepts(InterceptionType type)Object intercept(InterceptionType, T, InvocationContext)

DecoratorT

Type getDelegateType()Set<Annotation> getDelegateQualifiers()Set<Type> getDecoratedTypes()

ProducerT

T produce(CreationalContext<T>)void dispose(T)Set<InjectionPoint> getInjectionPoints()

InjectionTargetT

void inject(T, CreationalContext<T>)void postConstruct(T)void preDestroy(T)

InjectionPoint

Type getType()Set<Annotation> getQualifiers()Bean<?> getBean()Member getMember()Annotated getAnnotated()boolean isDelegate()boolean isTransient()

ObserverMethodT

Class<?> getBeanClass()Type getObservedType()Set<Annotation> getObservedQualifiers()Reception getReception()TransactionPhase getTransactionPhase()void notify(T)

EventMetadata

Set<Annotation> getQualifiers()InjectionPoint getInjectionPoint()Type getType()

Page 117: Extending Java EE with CDI and JBoss Forge

SPIprovidingCDIentrypoints

IterableT

Iterator<T> iterator()void forEach()Spliterator<T> spliterator()

InstanceT

T get()Instance<T> select()Instance<T> select();boolean isUnsatisfied()boolean isAmbiguous()void destroy()

CDIT

Set<CDIProvider> discoveredProvidersCDIProvider configuredProvider

CDI<Object> current()void setCDIProvider(CDIProvider provider)BeanManager getBeanManager()

BeanManager

Object getReference(Bean<?>, Type, CreationalContext<?> )Object getInjectableReference(InjectionPoint, CreationalContext<?> )Set<Bean<?>> getBeans(Type, Annotation[])Bean<? extends X> resolve(Set<Bean<? extends X>>)void validate(InjectionPoint)void fireEvent(Object, Annotation[])

boolean isQualifier(Class<? extends Annotation>)boolean isStereotype(Class<? extends Annotation>)boolean areQualifiersEquivalent(Annotation, Annotation)boolean areInterceptorBindingsEquivalent(Annotation, Annotation)Context getContext(Class<? extends Annotation>)ELResolver getELResolver()ExpressionFactory wrapExpressionFactory(ExpressionFactory)AnnotatedType<T> createAnnotatedType(Class<T>)InjectionTarget<T> createInjectionTarget(AnnotatedType<T>)InjectionTargetFactory<T> getInjectionTargetFactory(AnnotatedType<T>)BeanAttributes<T> createBeanAttributes(AnnotatedType<T>)Bean<T> createBean(BeanAttributes<T>, Class<X>, ProducerFactory<X>)InjectionPoint createInjectionPoint(AnnotatedField<?>)

some methods skipped

UnmanagedT

Unmanaged(BeanManager, Class<T>)Unmanaged(Class<T>)UnmanagedInstance<T> newInstance()

UnmanagedInstanceT

T get()UnmanagedInstance<T> produce()UnmanagedInstance<T> inject()UnmanagedInstance<T> postConstruct()UnmanagedInstance<T> preDestroy()UnmanagedInstance<T> dispose()

provides

Page 118: Extending Java EE with CDI and JBoss Forge

SPIdedicatedtoextensions

BeforeBeanDiscovery

addQualifier(Class<? extends Annotation>)addScope(Class<? extends Annotation>, boolean, boolean)addStereotype(Class<? extends Annotation>, Annotation[])addInterceptorBinding(Class<? extends Annotation>, Annotation[])addAnnotatedType(AnnotatedType<?>)

AfterTypeDiscovery

List<Class<?>> getAlternatives()List<Class<?>> getInterceptors()List<Class<?>> getDecorators()addAnnotatedType(AnnotatedType<?>, String)

AfterDeploymentValidation BeforeShutdown

AfterBeanDiscovery

addBean(Bean<?>)addObserverMethod(ObserverMethod<?>)addContext(Context)AnnotatedType<T> getAnnotatedType(Class<T>, String)Iterable<AnnotatedType<T>> getAnnotatedTypes(Class<T>)

ProcessAnnotatedTypeX

AnnotatedType<X> getAnnotatedType()void setAnnotatedType(AnnotatedType<X>)veto()

ProcessBeanX

Annotated getAnnotated()Bean<X> getBean()

ProcessBeanAttributesT

Annotated getAnnotated()BeanAttributes<T> getBeanAttributes()setBeanAttributes(BeanAttributes<T>)veto()

ProcessInjectionPointT, X

InjectionPoint getInjectionPoint()setInjectionPoint(InjectionPoint)

ProcessInjectionTargetX

AnnotatedType<X> getAnnotatedType()InjectionTarget<X> getInjectionTarget()setInjectionTarget(InjectionTarget<X>)

ProcessObserverMethodT, X

AnnotatedMethod<X> getAnnotatedMethod()ObserverMethod<T> getObserverMethod()

ProcessProducerT, X

AnnotatedMember<T> getAnnotatedMember()Producer<X> getProducer()setProducer(Producer<X>)

Page 119: Extending Java EE with CDI and JBoss Forge

AlltheseSPIinterfacesareeventscontainingmeta-modelSPI

TheseeventsfiredatboottimecanonlybeobservedinCDIextensions

Forinstance:

A ProcessAnnotatedType<T> eventisfiredforeachtypebeingdiscoveredatboottime

Observing ProcessAnnotatedType<Foo>allowsyoutoprevent Foo tobedeployedasabeanbycallingProcessAnnotatedType#veto()

Page 120: Extending Java EE with CDI and JBoss Forge

WegotthisJavadoc: Backtodemo

Page 121: Extending Java EE with CDI and JBoss Forge

Backtodemo Wedon’thavethecodeofthe BillingService

Createa BillingServiceExtension whichcallsBillingService

Usingobservers BillingServiceObserver

Extensionhastobeenabled

Page 122: Extending Java EE with CDI and JBoss Forge

CDI2.0

Page 123: Extending Java EE with CDI and JBoss Forge

AboutCDI2.0

WorkisinprogressonCDI2.0

Comeseethesession"CDI2.0iscoming"thursday2pmroom8

Oneofthenewfeaturesistheasynchronousevents

Thegoodnewsis:"youcantestittoday"

Page 124: Extending Java EE with CDI and JBoss Forge

Asynchronouseventexamplepublic class FirstBean { @Inject Event<Post> postEvent;

public void saveNewPost(Post myPost) {

postEvent.fireAsync(myPost); }}

public class SecondBean {

public void listenPost(@ObservesAsync Post post) { System.out.println("Received : " + evt.message()); }}

Weintroduceda fireAsync() method

Forbackwardcompatibilitywehadtoaddan @ObservesAsync observer

1

2

1

2

Page 125: Extending Java EE with CDI and JBoss Forge

Let’stestasynchronousevent

Weld3Alpha(previewofCDI2.0RI)isavailable

WildFlyincludesapatchmechanismtoupgradeimplementations

WecanpatchWildFlywithasimplecommand

./jboss-cli.sh --command="patch apply ~/wildfly-10.0.0.CR4-weld-3.0.0.Alpha13-patch.zip"

Page 126: Extending Java EE with CDI and JBoss Forge

Backtodemo

Let’saddasynchronousevent

Page 127: Extending Java EE with CDI and JBoss Forge

Conclusion

Page 128: Extending Java EE with CDI and JBoss Forge

References

CDISpecification-cdi-spec.org

Code&slidesrepository-github.com/antoinesd/cdi-forge-uni

SlidesgeneratedwithAsciidoctor,PlantUMLandDZSlidesbackend

Originalslidetemplate-DanAllen&SarahWhite

Page 129: Extending Java EE with CDI and JBoss Forge

AntoineSabot-DurandAntonioGoncalves@antoine_sd@agoncal