55
@antoine_sd @cdispec #CDI2 CDI II is coming Antoine Sabot-Durand Red Hat CDI spec lead

CDI 2.0 is coming

Embed Size (px)

Citation preview

Page 1: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI II is comingAntoine Sabot-Durand

Red HatCDI spec lead

Page 2: CDI 2.0 is coming

MicroProfile 1.0 Released!

Microservice Collaboration and Innovation in the Java Community

microprofilelunch.com, Thursday 11:30am - 2:00pm

Learn more at microprofile.io

MicroProfile BOF, Tuesday 10:30 - 11:30, Hilton Lombard Room(3rd tower, 6th floor)

Page 3: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Me, Myself and I

Antoine Sabot-Durand

Software Engineer at Red Hat

CDI spec lead

CDI evangelist

Follow me: @antoine_sd

Follow CDI: @cdispec

Page 4: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Agenda

Flashback on CDI & CDI 2.0 status

CDI 2.0 new features

Java SE support

Enhancing events

Metadata configurators

Interceptor and Decorators on Produced / custom beans (coming)

Questions and Feedback

Page 5: CDI 2.0 is coming

Previously on CDI

Page 6: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI Timeline

Dec 2009 June 2013 Apr 2014 Sep 2014

CDI 1.0

(Jav

a EE

6)

CDI 1.1

(Jav

a EE

7)

CDI 1.2

(1.1 M

R)

CDI 2.0

Star

ts

jan 2017

CDI 2.0

relea

sed

Page 7: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 1.0 - December 2009

A well-defined lifecycle for stateful objects bound to lifecycle contexts

Where the set of contexts is extensible

A type-safe dependency injection mechanism without verbose configuration

Dependencies can be selected at development or deployment time

Type-safe decorators and interceptors

An event notification model

An SPI allowing portable extensions to integrate cleanly with the container

Page 8: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 1.1 / 1.2 – June 2013 / April 2014

Add automatic enablement of CDI in Java EE

Add introspection with event, bean, decorator and interceptor meta data

Ease access to bean manager from outside CDI with CDI class

Add global enablement of interceptors using the @Priority annotation

Add Unmanaged allowing easy access to non-contexutal instances

Spec clarification

Page 9: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 1.2 - April 2014

Clarification in the spec regarding:

CDI Lifecycle

Events

Reworking Bean defining annotation to avoid conflict with other JSR 330 frameworks

Clarification on conversation resolution

OSGi official support in the API

Page 10: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 2.0 status

JSR 365 started in September 2014

EDR1 released in 2015

EDR2 released in august.

Weld 3 Aplha 17 is the RI for EDR2

Release expected in January 2017

Page 11: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

cdi-spec.org

Page 12: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 2.0 new features

Page 13: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Java SE supportusing CDI outside Java EE

Page 14: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Java SE support - Why?

To align on many other Java EE spec which support Java SE bootstrapping

To boost CDI adoption for Spec and Frameworks

To provide a mean of building new stacks out of Java EE

Page 15: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

What did we do?

CDI Specification

CDI Core CDI for Java EECDI for Java SE

Page 16: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public static void main(String[] args) { SeContainer container = SeContainerInitializer.newInstance() .disableDiscovery() .addBeanClasses(MyService.class) .initialize(); MyService service = container.select(MyService.class).get(); service.sayHello(); container.close();}

Java SE bootstrap API

Page 17: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Enhancing eventsMaking popular feature even more popular

Page 18: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Enhancing events

CDI events are a very loved feature

We took a very long time to see how to enhance them

In CDI 2.0 we are introducing

Event ordering

Asynchronous events

Page 19: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Events ordering

By adding a @Priority (from commons annotations) on an observer.

The lowest value is first

Observers with no explicit priority have a middle range priority

Allowing observer to be called last

Observer with the same priority are called in an undefined order

No priority on async events

Page 20: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public void observer1(@Observes @Priority(1) Payload p) { }

public void observer2(@Observes @Priority(2) Payload p) { }

Events ordering

Page 21: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public class MyExtension implements Extension { public void firstPat(@Observes @Priority(1) ProcessAnnotatedType<?> pat) { … }

public void secondPat(@Observes @Priority(2) ProcessAnnotatedType<?> pat) { … }}

Events ordering in extensions

Page 22: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 1.x: Sync / Async

Sync / Async is not specified

The immutable status of the payload is not specified

Implementations use a Sync model

The payload is mutated in some implementations / framework

Going async “blindly” might raise problems…

Page 23: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

@InjectEvent<Payload> event;

public void someBSCriticalBusinessMethod() { event.fire(new Payload());}

Synchronous events - firing pattern

Page 24: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public void callMe(@Observes Payload payload) { // Do something with the event }

Synchronous events - observing pattern

Page 25: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Events are sync in CDI 1

Right now:

All the observers are called in the firing thread

In no particular order (at least not specified)

The payload may be mutated

Page 26: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Events and contexts

Contexts:

Two contexts are critical: transactions and HTTP requests / sessions

Events are aware of those contexts

In an all-sync world, everything is fine

But in an async world, we will be in trouble

Page 27: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Asynchronous Events

So designing backward compatible async events is more tricky than it looks:

A currently sync event should remain sync

Going sync / async should be a decision taken from the firing side

Being sync should be possible from the observing side

Page 28: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

@InjectEvent<Payload> event;

public void someEvenMoreCriticalBusinessMethod() { event.fireAsync(new Payload());}

Async events - firing pattern

Page 29: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public void callMe(@ObservesAsync Payload payload) { // I am called in another thread}

Async events - observing pattern

Page 30: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Sync vs Async Events in a nutshell

callMe(@Observes payload) callMe(@ObservesAsync payload)

event.fire(payload) Sync call Not notified

event.fireAsync(payload) Not notified Async call

Page 31: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

@InjectEvent<PanelUpdater> event;

public void someOtherCriticalBusinessMethod() { event.fireAsync(new PanelUpdater(green), executor); }

Adding an Executor to fireAsync

Page 32: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

@InjectEvent<PanelUpdater> event;

public void someOtherCriticalBusinessMethod() { event.fireAsync(new PanelUpdater(green), SwingUtilities::invokeLater);}

Async event in the GUI thread

Page 33: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

@InjectEvent<PanelUpdater> event;

public void someOtherCriticalBusinessMethod() { CompletionStage<PanelUpdater> stage = event.fireAsync(new PanelUpdater(green), SwingUtilities::invokeLater);}

Handling exceptions

Page 34: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Handling exceptions

Exception in one async observer doesn’t stop execution as in sync observer

One of the reasons why firing async event doesn’t trigger sync observers

Event.fireAsync returns a CompletionStage

Allowing integration of async events in standard Java 8 async pipeline

Page 35: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Handling exceptions

The Exception in fireAsync returned CompletionStage is

CompletionException

It holds all the exceptions in the suppressed exception set

Page 36: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Handling exceptions

Exception handling is done with the Standard Java 8 async api, with:

stage.whenComplete() to deal with result or exception

stage.handle() same as above but allows transformation of stage

stage.exceptionally() to only treat exception case

Page 37: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

SPI enhancementNew configurators for meta data

Page 38: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Configurators for meta-data

Some meta-data are very verbose to create

AnnotatedType

Bean

InjectionPoint

ObserverMethod

If you only need to add info to an existing meta-data, it’s very boring

Page 39: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Example with CDI 1.2

I have a legacy framework

I want to adapt it for CDI

I need to detect all @CacheContext annotations on fields…

... And transform them in injection point

I’ll use an extension to replace @CacheContext annotation by @Inject in AnnotatedTypes

Page 40: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Example 1/7

First we need to implement an AnnotatedType to decorate the original one and modify AnnotatedField set

Page 41: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public class AutoInjectingAnnotatedType<X> implements AnnotatedType<X> { private final AnnotatedType<X> delegate; private final Set<AnnotatedField<? super X>> fields; public AutoInjectingAnnotatedType(AnnotatedType<X> delegate) { this.delegate = delegate; fields = new HashSet<>(); for (AnnotatedField<? super X> field : delegate.getFields()) { if (field.isAnnotationPresent(CacheContext.class)) fields.add(new AutoInjectingAnnotatedField(field)); else fields.add(field); } }…

Example 2/7

Page 42: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

… public Set<AnnotatedField<? super X>> getFields() { return fields; } public Class<X> getJavaClass() { return delegate.getJavaClass(); } // 7 more similar methods }

Example 3/7

Page 43: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Example 4/7Then we need to do the same for AnnotatedField to add @Inject to the field annotations set

public class AutoInjectingAnnotatedField<X> implements AnnotatedField<X> { private final Set<Annotation> annotations; private final AnnotatedField<X> delegate; public AutoInjectingAnnotatedField(AnnotatedField<X> delegate) { this.delegate = delegate; annotations = new HashSet<>(delegate.getAnnotations()); annotations.add(new InjectLiteral()); }…

Page 44: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public <T extends Annotation> T getAnnotation(Class<T> annotationType) { if (annotationType.equals(Inject.class)) return (T) new InjectLiteral(); return delegate.getAnnotation(annotationType); } public Set<Annotation> getAnnotations() { return annotations; }

...

Example 5/7

Page 45: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { if (annotationType.equals(Inject.class)) return true; return delegate.isAnnotationPresent(annotationType); }

public Set<Type> getTypeClosure() { return delegate.getTypeClosure(); }

// 4 similar methods }

Example 6/7

Page 46: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Example 7/7Finaly we need to write the extension to use our custom AnnotatedType and AnnotatedField

public class AutoInjectExtension implements Extension {public <T> void CreateIP( @Observes @WithAnnotations(CacheContext.class) ProcessAnnotatedType<T> pat) { pat.setAnnotatedType( new AutoInjectingAnnotatedType<T>(pat.getAnnotatedType())); }}

Page 47: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

In CDI 2.0

We introduced configurators, helping creation of these metadata

This configurators are accessible thru container lifecycle events

They are automatically built by the container at the end of

observer invocation

Page 48: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

In CDI 2.0All the previous code fits in this extension

public class AutoInjectExtension implements Extension {public <T> void CreateIP( @Observes @WithAnnotations(CacheContext.class) ProcessAnnotatedType<T> pat) { pat.configureAnnotatedType().filterFields( f -> f.isAnnotationPresent(CacheContext.class) ) .forEach(f -> f.add(InjectLiteral.INSTANCE)); }}

Page 49: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

AOP enhancementSupport AOP on custom or produced bean

Page 50: CDI 2.0 is coming
Page 51: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Support AOP on producer

In CDI 1.x you cannot bind an interceptor to a produced bean

When you write:

@Transactional is applied to producer method

@Produces@Transactional public MyService produceService() {

...}

Page 52: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Support AOP on producerAnswer is probably the new InterceptionProxyFactory

This factory uses an AnnotatedType to know where adding interceptor bindings in the class

Could also be used in Custom Bean create method

public interface InterceptionProxyFactory<T> { InterceptionProxyFactory<T> ignoreFinalMethods(); AnnotatedTypeConfigurator<T> configure(); <T> T createInterceptionProxy(T InstanceToWrap);}

Page 53: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

@Produces@RequestScopedpublic MyClass createJpaEmAssumed(InterceptionProxyFactory<MyClass> ipf) { AnnotatedTypeConfigurator<MyClass> atc = ipf.configure(); atc.filterMethods(m -> m.getJavaMember().getName().equals("doSomething")) .findFirst() .ifPresent(m -> m.add(new AnnotationLiteral<Transactional>() { })); return ipf.createInterceptionProxy(new MyClass());}

Add @transaction on one produced bean method

Page 54: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

CDI 2.0 needs you

CDI 2.0 specification is open to everyone

Come on join us on the mailing list and IRC channel

All infos on http://cdi-spec.org or by following to @cdispec on twitter

The more we are the more we’ll deliver

Page 55: CDI 2.0 is coming

@antoine_sd @cdispec#CDI2

Which JSR you’ll use 365 days a year?…

JSR 365