Warum CDI oder
gibt es einen tieferen Sinn dahinter?
warum denn CDI ? ;-)
@SvenRuppert 4/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
oft gehörte Antwort
kürzere Notation.. *oje*
Manchmal ist die Notation per Inject kürzer. Sobald allerdings die einzelnen
Qualifier dazukommen, ist meist der Aufwand zum Aufruf eines Konstruktors
kaum unterschiedlich.
Verkürzen der Notation ist natürlich nicht das Ziel von CDI
@SvenRuppert 5/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
lösen/entfernen von statischen Abhängigkeiten
@SvenRuppert 6/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
lösen/entfernen von statischen Abhängigkeiten
Dieser Punkt ist einer der wesentlichen.
Also: Wie kann man zur Entwicklungszeit die Abhängigkeiten zu den anderen
Projektmodulen möglichst gering halten?
@SvenRuppert 7/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
lösen/entfernen von statischen Abhängigkeiten
Dieser Punkt ist einer der wesentlichen.
Also: Wie kann man zur Entwicklungszeit die Abhängigkeiten zu den anderen
Projektmodulen möglichst gering halten?
Gehen wir von der Definition einer Liste aus. Als Rückgabewert einer Methode
wird eine Instanz der Implementierung von List verwendet.
publicList<Data>execute(){...}; JAVA
@SvenRuppert 8/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Damit sind nachfolgende Aufrufer nicht mehr an die Implementierung der List
gebunden.
importjava.util.List;
importjava.util.ArrayList;
publicList<Data>execute(){
finalList<Data>result=newArrayList<>();
//....
returnresult;
}
JAVA
@SvenRuppert 9/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Damit sind nachfolgende Aufrufer nicht mehr an die Implementierung der List
gebunden.
In der Methode jedoch besteht meist die Abhängigkeit zu der entsprechenden
Implementierung obwohl auch das meist nicht notwendig ist.
importjava.util.List;
importjava.util.ArrayList;
publicList<Data>execute(){
finalList<Data>result=newArrayList<>();
//....
returnresult;
}
JAVA
@SvenRuppert 10/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList
verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet.
@SvenRuppert 11/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList
verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet.
Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig.
@SvenRuppert 12/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList
verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet.
Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig.
Sollte sich zur Laufzeit herausstellen, das die Wahl dieser Implementierung nicht
optimal gewesen ist, muss der Quelltext angepasst und neu verteilt werden.
@SvenRuppert 13/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList
verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet.
Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig.
Sollte sich zur Laufzeit herausstellen, das die Wahl dieser Implementierung nicht
optimal gewesen ist, muss der Quelltext angepasst und neu verteilt werden.
z.B. Mit std SE Mitteln kann man das durch entsprechende Factories lösen.
@SvenRuppert 14/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Mit std SE Mitteln kann man das durch entsprechende Factories lösen.
Beispielhaft soll hier folgende Implementierung verwendet werden.
importjava.util.ArrayList;
importjava.util.LinkedList;
importjava.util.List;
publicclassListFactory{
publicListcreateArrayList() {returnnewArrayList();}
publicListcreateLinkedList(){returnnewLinkedList();}
publicListcreateList() {returnnewArrayList();}
}
JAVA
@SvenRuppert 15/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Haben wir damit etwas erreicht?
@SvenRuppert 16/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Haben wir damit etwas erreicht?
... bzw was haben wir damit erreicht?
@SvenRuppert 17/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Haben wir damit etwas erreicht?
... bzw was haben wir damit erreicht?
z.B. Die Entwickler verwenden nun diese Factory.
@SvenRuppert 18/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Haben wir damit etwas erreicht?
... bzw was haben wir damit erreicht?
z.B. Die Entwickler verwenden nun diese Factory. -> wenn sie wissen das es diese
gibt! ;-)
@SvenRuppert 19/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Vorher / Nachher (1/2)
importjava.util.List;
importjava.util.ArrayList;
publicList<Data>execute(){
finalList<Data>result=newArrayList<>();
//....
returnresult;
}
JAVA
@SvenRuppert 20/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Vorher / Nachher (2/2)
importjava.util.List;
importjava.util.ArrayList;
publicList<Data>execute(){
finalList<Data>result=newArrayList<>();
//....
returnresult;
}
importjava.util.List;
importorg.rapidpm.demo.ListFactory;
publicList<Data>execute(){
finalListlist=newListFactory().createArrayList();
//....
returnresult;
}
JAVA
@SvenRuppert 21/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
@SvenRuppert 22/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
Die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch explizit
gefallen.
@SvenRuppert 23/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
Die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch explizit
gefallen.
Die Abhängigkeit zur Factory wurde hinzugefügt.
@SvenRuppert 24/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
Die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch explizit
gefallen.
Die Abhängigkeit zur Factory wurde hinzugefügt.
Die Implementierung der ListFactory selber hat auch wieder die statischen
Abhängigkeiten zu allen vorgesehenen Implementierungen.
@SvenRuppert 25/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen
Implementierungen
@SvenRuppert 26/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen
Implementierungen
Anforderung Nr 2: keine statischen Entscheidungen für spezifische
Implementierungen
@SvenRuppert 27/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen
Implementierungen
Anforderung Nr 2: keine statischen Entscheidungen für spezifische
Implementierungen
Was ist jetzt eine mögliche Lösung ???
@SvenRuppert 28/122
Lösungsversuch Nr 1
basierend auf Java SE
Eine etwas dynamischere Lösung...
@SvenRuppert 29/122
Lösungsversuch Nr 1
basierend auf Java SE
Eine etwas dynamischere Lösung...
importjava.util.ArrayList;
importjava.util.LinkedList;
importjava.util.List;
importorg.rapidpm.demo.cdi.commons.registry.ContextResolver;
publicclassListFactory{
publicListcreateList(finalContextResolvercontextResolver){
if(contextResolver==null){returncreateArrayList();}
else{
if(contextResolver.resolveContext()){returncreateArrayList();}
else{returncreateLinkedList();}
}
}
}
JAVA
@SvenRuppert 30/122
Lösungsversuch Nr 1
basierend auf Java SE
Eine etwas dynamischere Lösung...
Die Komplexität der Entscheidung liegt nun im ContextResolver
@SvenRuppert 31/122
Lösungsversuch Nr 1
basierend auf Java SE
Eine etwas dynamischere Lösung...
Die Komplexität der Entscheidung liegt nun im ContextResolver
Abhängigkeit in der Factory zum ContextResolver hinzugefügt
@SvenRuppert 32/122
Lösungsversuch Nr 1
basierend auf Java SE
Eine etwas dynamischere Lösung...
Die Komplexität der Entscheidung liegt nun im ContextResolver
Abhängigkeit in der Factory zum ContextResolver hinzugefügt
Gewonnen: zur Laufzeit sich für eine Implementierung entscheiden.
@SvenRuppert 33/122
Lösungsversuch Nr 1
basierend auf Java SE
Möchte man nun die Factory so erstellen, dass diese wiederum keine statischen
Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste
hat, muss eine z.B. Registry gebaut werden.
@SvenRuppert 34/122
Lösungsversuch Nr 1
basierend auf Java SE
Möchte man nun die Factory so erstellen, dass diese wiederum keine statischen
Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste
hat, muss eine z.B. Registry gebaut werden.
Dort kann man zur Laufzeit die jeweiligen Implementierungen registrieren und
für eine Auflösung zur Verfügung stellen.
@SvenRuppert 35/122
Lösungsversuch Nr 1
basierend auf Java SE
Möchte man nun die Factory so erstellen, dass diese wiederum keine statischen
Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste
hat, muss eine z.B. Registry gebaut werden.
Dort kann man zur Laufzeit die jeweiligen Implementierungen registrieren und
für eine Auflösung zur Verfügung stellen.
Hier hilft CDI durch seine Konzepte, ohne das man sich mit der
Basisimplementierung der Infrastruktur beschäftigen muss.
@SvenRuppert 36/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
@SvenRuppert 37/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
@InjectListlist; JAVA
@SvenRuppert 38/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
@Inject@CDILegacyTestListlist; JAVA
@SvenRuppert 39/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
@Inject@CDILegacyTestListlist;
@Produces@CDILegacyTest
publicListcreateList(...){...}
JAVA
@SvenRuppert 40/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
@Inject@CDILegacyTestListlist;
@Produces@CDILegacyTest
publicListcreateList(InjectionPointinjectionPoint,
BeanManagerbeanManager,ContextResolvercontextResolver){
....
}
JAVA
@SvenRuppert 41/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
@Inject@CDILegacyTestListlist;
@Produces@CDILegacyTest
publicListcreateList(InjectionPointinjectionPoint,
BeanManagerbeanManager,ContextResolvercontextResolver){
booleanb=contextResolver.resolveContext(...); //treffenderEntscheidungen...
if(b){returnnewLinkedList();}else{returnnewArrayList();}
}
JAVA
@SvenRuppert 42/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen werden per @Inject durch den Container zur Verfügung gestellt
Aber leider ist das immer noch zu dem Zeitpunkt zu dem die umliegende Instanz
erzeugt wird.
@Inject@CDILegacyTestListlist;
@Produces@CDILegacyTest
publicListcreateList(InjectionPointinjectionPoint,
BeanManagerbeanManager,ContextResolvercontextResolver){
booleanb=contextResolver.resolveContext(...); //treffenderEntscheidungen...
if(b){returnnewLinkedList();}else{returnnewArrayList();}
}
JAVA
@SvenRuppert 43/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden.
@SvenRuppert 44/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden.
Damit sind späte Entscheidungen möglich
@SvenRuppert 45/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden.
Damit sind späte Entscheidungen möglich
@Inject@CDILegacyTestInstance<List>listInstance; JAVA
@SvenRuppert 46/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden.
Damit sind späte Entscheidungen möglich
@Inject@CDILegacyTestInstance<List>listInstance;
//..später
finalListlist=listInstance.get();
JAVA
@SvenRuppert 47/122
endlich CDI ;-)
basierend auf Weld / WELD-SE
Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden
damit sind späte Entscheidungen möglich
@Inject@CDILegacyTestInstance<List>listInstance;
//..später
finalListlist=listInstance.get();
@Produces@CDILegacyTest
publicListcreateList(InjectionPointinjectionPoint,
BeanManagerbeanManager,ContextResolvercontextResolver){
booleanb=contextResolver.resolveContext(...); //treffenderEntscheidungen...
if(b){returnnewLinkedList();}else{returnnewArrayList();}
}
JAVA
@SvenRuppert 48/122
CDI
was wurde bis jetzt erreicht?
Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der
Vererbung
@SvenRuppert 49/122
CDI
was wurde bis jetzt erreicht?
Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der
Vererbung
Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt
@SvenRuppert 50/122
CDI
was wurde bis jetzt erreicht?
Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der
Vererbung
Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt
Für jede Entscheidung einen Producer
@SvenRuppert 51/122
CDI
was wurde bis jetzt erreicht?
Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der
Vererbung
Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt
Für jede Entscheidung einen Producer.. wie funktioniert das praktisch?
@SvenRuppert 52/122
CDI
was wurde bis jetzt erreicht?
Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der
Vererbung
Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt
Für jede Entscheidung einen Producer.. wie funktioniert das praktisch?
... sehen wir uns gleich noch an.... Bitte ein wenig Geduld...
@SvenRuppert 53/122
CDI
was wurde dafür in Kauf genommen?
statische Kopplung über AnnotationsLiterale:
@Inject@MyQualifierListliste; JAVA
@SvenRuppert 54/122
CDI
was wurde dafür in Kauf genommen?
statische Kopplung über AnnotationsLiterale:
schlechterer Umgang mit Generics
@Inject@MyQualifierListliste; JAVA
@SvenRuppert 55/122
CDI
was wurde dafür in Kauf genommen?
statische Kopplung über AnnotationsLiterale:
schlechterer Umgang mit Generics
keine Komplexitätsreduktion für den Entwickler
@Inject@MyQualifierListliste; JAVA
@SvenRuppert 56/122
CDI explained by code
HelloLogger zum aufwärmen/wiederholen
klassischer Fall, Logger im System
@Inject@CDILoggerLoggerlogger; JAVA
@SvenRuppert 57/122
CDI explained by code
HelloLogger zum aufwärmen/wiederholen
klassischer Fall, Logger im System
@Inject@CDILoggerLoggerlogger;
@Qualifier
@Retention(value=RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE})
public@interfaceCDILogger{}
JAVA
@SvenRuppert 58/122
CDI explained by code
HelloLogger zum aufwärmen/wiederholen
klassischer Fall, Logger im System
@Inject@CDILoggerLoggerlogger;
@Qualifier
@Retention(value=RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE})
public@interfaceCDILogger{}
@Produces@CDILogger
publicLoggerproduceLog4JLogger(InjectionPointiP,BeanManagerbeanManager){
finalClass<?>declaringClass=iP.getMember().getDeclaringClass();
returnnewLogger(declaringClass);
}
JAVA
@SvenRuppert 59/122
CDI explained by code
HelloLogger zum aufwärmen/wiederholen
klassischer Fall, Logger im System
@Inject@CDILoggerLoggerlogger;
@Qualifier
@Retention(value=RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE})
public@interfaceCDILogger{}
@Produces@CDILogger
publicLoggerproduceLog4JLogger(InjectionPointiP,BeanManagerbeanManager){
finalClass<?>declaringClass=iP.getMember().getDeclaringClass();
returnnewLogger(declaringClass);//Loggernichtgemanaged!!!
}
JAVA
@SvenRuppert 60/122
CDI explained by code
HelloLogger zum aufwärmen / Hat uns das jetzt richtig weitergebracht?
Referenz auf Factory wird ersetzt durch Qualifier. :-(
@Inject@CDILoggerLoggerlogger; JAVA
@SvenRuppert 61/122
CDI explained by code
HelloLogger zum aufwärmen / Hat uns das jetzt richtig weitergebracht?
Referenz auf Factory wird ersetzt durch Qualifier. :-(
Spezifische Producer losgelöst von den anderen Producern
@Inject@CDILoggerLoggerlogger; JAVA
@SvenRuppert 62/122
CDI explained by code
HelloLogger zum aufwärmen / Hat uns das jetzt richtig weitergebracht?
Referenz auf Factory wird ersetzt durch Qualifier. :-(
Spezifische Producer losgelöst von den anderen Producern
zentrale Stelle für context-bezogene Entscheidungen
@Inject@CDILoggerLoggerlogger; JAVA
@SvenRuppert 63/122
CDI explained by code
Qualifier und AnnotationsLiterale
@Inject@CDILoggerLoggerlogger; JAVA
@SvenRuppert 64/122
CDI explained by code
Qualifier und AnnotationsLiterale
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
@SvenRuppert 65/122
CDI explained by code
Qualifier und AnnotationsLiterale
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
@Producer@CDILoggerLoggercreate(..){
AnnotationsLiteral<T>prodAL=contextResolver.resolve(..);
};
JAVA
@SvenRuppert 66/122
CDI explained by code
Qualifier und AnnotationsLiterale
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
@Producer@CDILoggerLoggercreate(BeanManagerbm,ContextResolvercr){
AnnotationsLiteral<T>prodAL=contextResolver.resolve(..);
returncreator.getManagedInstance(Logger.class,annotationLiteral);
};
JAVA
@SvenRuppert 67/122
CDI explained by code
Qualifier und AnnotationsLiterale
Es wird dynamisch auf ein AnnotationsLiteral aufgelöst.
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
@Producer@CDILoggerLoggercreate(BeanManagerbm,ContextResolvercr){
AnnotationsLiteral<T>prodAL=contextResolver.resolve(..);
returncreator.getManagedInstance(Logger.class,annotationLiteral);
};
JAVA
@SvenRuppert 68/122
CDI explained by code
Qualifier und AnnotationsLiterale
Es wird dynamisch auf ein AnnotationsLiteral aufgelöst.
AnnotationsLiteral und Klasse -> Auswahl des Producers
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
@Producer@CDILoggerLoggercreate(BeanManagerbm,ContextResolvercr){
AnnotationsLiteral<T>prodAL=contextResolver.resolve(..);
returncreator.getManagedInstance(Logger.class,annotationLiteral);
};
JAVA
@SvenRuppert 69/122
CDI explained by code 1 / 6
ContextResolver / aus der Sicht des Entwicklers
@InjectCDIContextcontext;//z.B.einSingleton
@InjectContextResolvercr;
@Test
publicvoidtestMockedModus001()throwsException{
Assert.assertFalse(context.isMockedModusActive());
finalAnnotationLiteralannotationLiteralProd=cr.resolveContext(this.getClass());
Assert.assertEquals(newAnnotationLiteral<CDICommons>(){},annotationLiteralProd);
}
JAVA
@SvenRuppert 70/122
CDI explained by code 1 / 6
ContextResolver / aus der Sicht des Entwicklers
@InjectCDIContextcontext;//z.B.einSingleton
@InjectContextResolvercr;
@Test
publicvoidtestMockedModus001()throwsException{
Assert.assertFalse(context.isMockedModusActive());
finalAnnotationLiteralannotationLiteralProd=cr.resolveContext(this.getClass());
Assert.assertEquals(newAnnotationLiteral<CDICommons>(){},annotationLiteralProd);
((TestContext)context).setTestModus(true);
Assert.assertTrue(context.isMockedModusActive());
}
JAVA
@SvenRuppert 71/122
CDI explained by code 1 / 6
ContextResolver / aus der Sicht des Entwicklers
@InjectCDIContextcontext;//z.B.einSingleton
@InjectContextResolvercr;
@Test
publicvoidtestMockedModus001()throwsException{
Assert.assertFalse(context.isMockedModusActive());
finalAnnotationLiteralannotationLiteralProd=cr.resolveContext(this.getClass());
Assert.assertEquals(newAnnotationLiteral<CDICommons>(){},annotationLiteralProd);
((TestContext)context).setTestModus(true);
Assert.assertTrue(context.isMockedModusActive());
finalAnnotationLiteralannotationLiteral=cr.resolveContext(this.getClass());
Assert.assertEquals(newAnnotationLiteral<CDICommonsMocked>(){},annotationLiteral);
}
JAVA
@SvenRuppert 72/122
CDI explained by code 1 / 6
ContextResolver / aus der Sicht des Entwicklers
@SvenRuppert 73/122
CDI explained by code 1 / 6
ContextResolver / aus der Sicht des Entwicklers
@SvenRuppert 74/122
CDI explained by code 2a / 6
ContextResolver
Die Annotation mit @CDINotMapped, um das Interface explizit in den
Namensraum zu setzen
@CDINotMapped
publicinterfaceCDIContext{
publicbooleanisMockedModusActive();
}
JAVA
@SvenRuppert 75/122
CDI explained by code 2b / 6
ContextResolver
Mit klassischen Interzeptoren kann man Querschnittsthemen deklarieren.
Nur allgemein umschalten auf Mocked/NotMocked möglich?
@InterceptorBinding
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(value=RetentionPolicy.RUNTIME)
@Inherited
public@interfaceCheckMockedContext{}
publicinterfaceContextResolver{
@CheckMockedContext
publicAnnotationLiteralresolveContext(finalClass<?>targetClass);
}
JAVA
@SvenRuppert 76/122
CDI explained by code 3a / 6
ContextResolver
@Interceptor@CheckMockedContext
publicclassMockedInterceptorimplementsSerializable{
@InjectCDIContextcontext;
private@Inject@CDILoggerLoggerlogger;
@AroundInvoke
publicObjectcheckMockedMode(InvocationContextctx)throwsException{
if(context.isMockedModusActive()){
if(logger.isDebugEnabled()){logger.debug("MockedModusactive");}
returnnewAnnotationLiteral<CDICommonsMocked>(){};
}else{
returnctx.proceed();
}
}
}
JAVA
@SvenRuppert 77/122
CDI explained by code 3b / 6
ContextResolver
Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar
@SvenRuppert 78/122
CDI explained by code 3b / 6
ContextResolver
Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar
Benötigt wird aber evtl differenziertes Umschalten.
@SvenRuppert 79/122
CDI explained by code 3b / 6
ContextResolver
Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar
Benötigt wird aber evtl differenziertes Umschalten.
Interzeptoren werden statisch definiert - schade....
@SvenRuppert 80/122
CDI explained by code 4a / 6
ContextResolver
@CDICommons
public class DefaultContextResolver implements ContextResolver {
@Inject @CDILogger Logger logger; @Inject BeanManager beanManager;
public Set<ContextResolver> gettAllContextResolver() {
final Set<ContextResolver> resultSet = new HashSet<>();
final Set<Bean<?>> allBeans = beanManager
.getBeans(ContextResolver.class, new AnnotationLiteral<Any>() {});
allBeans.forEach(b-> b.getTypes().stream()
.filter(t -> t.equals(ContextResolver.class))
.filter(r -> !r.getClass().isAnnotationPresent(CDICommonsMocked.class))
.forEach(t -> {
final ContextResolver cr = ((Bean<ContextResolver>) b)
.create(beanManager.createCreationalContext((Bean<ContextResolver>) b));
resultSet.add(cr);
}));
return resultSet;
}
JAVA
@SvenRuppert 81/122
CDI explained by code 4b / 6
ContextResolver
publicSet<ContextResolver>gettAllMockedContextResolver(){
finalSet<ContextResolver>resultSet=newHashSet<>();
finalSet<Bean<?>>allBeans=beanManager
.getBeans(ContextResolver.class,newAnnotationLiteral<CDICommonsMocked>(){});
allBeans.forEach(b->b.getTypes().forEach(type->{
if(type.equals(ContextResolver.class)){
finalContextResolvert=((Bean<ContextResolver>)b)
.create(beanManager.createCreationalContext((Bean<ContextResolver>)b));
resultSet.add(t);
}
}));
returnresultSet;
}
JAVA
@SvenRuppert 82/122
CDI explained by code 4c / 6
ContextResolver
publicAnnotationLiteralresolveContext(ClasstargetClass){
Stream<ContextResolver>contextResolversMocked=gettAllMockedContextResolver().stream();
Stream<ContextResolver>contextResolvers=gettAllContextResolver().stream();
returncontextResolversMocked
.filter(r->(r.resolveContext(targetClass)!=null))
.map(r->r.resolveContext(targetClass))
.findFirst().orElse(
contextResolvers
.filter(r->!r.getClass().isAnnotationPresent(CDICommonsMocked.class))
.filter(r->!r.getClass().equals(DefaultContextResolver.class))
.filter(r->(r.resolveContext(targetClass)!=null))
.map(r->r.resolveContext(targetClass))
.findFirst().orElse(null)
);
}
JAVA
@SvenRuppert 83/122
CDI explained by code 5 / 6
ContextResolver
@Singleton
publicclassTestContextimplementsCDIContext{
privatebooleantestModus=false;
@OverridepublicbooleanisMockedModusActive(){returntestModus;}
publicbooleanisTestModus(){returntestModus;}
publicvoidsetTestModus(booleantestModus){this.testModus=testModus;}
}
publicclassTestContextResolverimplementsContextResolver{
@InjectCDIContextcontext;
@CheckMockedContext
@OverridepublicAnnotationLiteralresolveContext(Class<?>targetClass){
//entscheideobDuzuständigbist
returnnewAnnotationLiteral<CDICommons>(){};
}
}
JAVA
@SvenRuppert 84/122
CDI explained by code 6 / 6
ContextResolver
Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren.
@SvenRuppert 85/122
CDI explained by code 6 / 6
ContextResolver
Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren.
ContextResolver sind immer nur in ihrem fachlichen Bereich aktiv
@SvenRuppert 86/122
CDI explained by code 6 / 6
ContextResolver
Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren.
ContextResolver sind immer nur in ihrem fachlichen Bereich aktiv
Unterscheidung auf z.B. Mandantenebene leicht realisierbar
@SvenRuppert 87/122
CDI explained by code 1 / 7
CDI managed DynamicObjectAdapter - besserer Decorator
klassischer Decorator in CDI
@Decorator
publicabstractclassCoderDecoratorimplementsCoder{
@Inject@Delegate@AnyCodercoder;
publicStringcodeString(Strings,inttval){
intlen=s.length();
return"""+s+""becomes"+"""+coder.codeString(s,tval)
+"","+len+"charactersinlength";
}
}
Insidebeans.xml
<decorators>
<class>decorators.CoderDecorator</class>
</decorators>
JAVA
@SvenRuppert 88/122
CDI explained by code 2 / 7
CDI managed DynamicObjectAdapter - der bessere Decorator
Ein Decorator in CDI muss in der beans.xml definiert werden.
@SvenRuppert 89/122
CDI explained by code 2 / 7
CDI managed DynamicObjectAdapter - der bessere Decorator
Ein Decorator in CDI muss in der beans.xml definiert werden.
Klasse mit einer speziellen Annotation @Decorator
@SvenRuppert 90/122
CDI explained by code 2 / 7
CDI managed DynamicObjectAdapter - der bessere Decorator
Ein Decorator in CDI muss in der beans.xml definiert werden.
Klasse mit einer speziellen Annotation @Decorator
Innerhalb des Decorators muss die Instanz des Originals injiziert werden
@SvenRuppert 91/122
CDI explained by code 2 / 7
CDI managed DynamicObjectAdapter - der bessere Decorator
Ein Decorator in CDI muss in der beans.xml definiert werden.
Klasse mit einer speziellen Annotation @Decorator
Innerhalb des Decorators muss die Instanz des Originals injiziert werden
Decorator muss von der Original-Implementierung oder dem Interface ableiten
@SvenRuppert 92/122
CDI explained by code 2 / 7
CDI managed DynamicObjectAdapter - der bessere Decorator
Ein Decorator in CDI muss in der beans.xml definiert werden.
Klasse mit einer speziellen Annotation @Decorator
Innerhalb des Decorators muss die Instanz des Originals injiziert werden
Decorator muss von der Original-Implementierung oder dem Interface ableiten
... geht das auch schöner ?
@SvenRuppert 93/122
CDI explained by code 3 / 7
CDI managed DynamicObjectAdapter - der bessere Decorator
Aus der Sicht des Entwicklers
@CDINotMapped
publicinterfaceDemoLogic{
publicdefaultintadd(inta,intb){ returna+b;}
publicdefaultintsub(inta,intb){ returna-b;}
}
@CDINotMapped
publicclassDemoLogicAdapter_AimplementsDemoLogic{
publicintadd(inta,intb){
returna+b+100;
}
}
@Singleton //sollteschonbekanntsein;-)
publicclassContext{publicbooleanoriginal=true;}
JAVA
@SvenRuppert 94/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
@SvenRuppert 95/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
@SvenRuppert 96/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
@SvenRuppert 97/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
@SvenRuppert 98/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
Context-Switch auf mandantenabhängige Implementierung
@SvenRuppert 99/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
Context-Switch auf mandantenabhängige Implementierung
Holen einer Instanz der DemoLogic
@SvenRuppert 100/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
Context-Switch auf mandantenabhängige Implementierung
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
@SvenRuppert 101/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
Context-Switch auf mandantenabhängige Implementierung
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 102.
@SvenRuppert 102/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
Context-Switch auf mandantenabhängige Implementierung
Holen einer Instanz der DemoLogic
Aufruf der Methode add(1,1)
Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 102.
Kaffee trinken.
@SvenRuppert 103/122
CDI explained by code 4b / 7
CDI managed DynamicObjectAdapter - besserer Decorator
@Inject@DynamicDecoratorTestInstance<DemoLogic>demoLogic;
@InjectContextcontext;
@Test
publicvoidtestDemoLogicOriginalTest()throwsException{
Assert.assertNotNull(demoLogic);
finalDemoLogicdemoLogic1=demoLogic.get();
finalintadd=demoLogic1.add(1,1);
Assert.assertEquals(2,add);
System.out.println("add="+add);
context.original=false;
finalDemoLogicdemoLogic2=demoLogic.get();
finalintaddAdapted=demoLogic2.add(1,1);
Assert.assertEquals(102,addAdapted);
System.out.println("addAdapted="+addAdapted);
}
JAVA
@SvenRuppert 104/122
CDI explained by code 4c / 7
CDI managed DynamicObjectAdapter - besserer Decorator
manuelles aktivieren von CDI.. yepp das geht
public<T>TactivateCDI(Tt){
finalClassaClass=t.getClass();
if(logger.isDebugEnabled()){logger.debug("activateCDI->"+aClass);}
AnnotatedTypeannotationType=beanManager.createAnnotatedType(aClass);
InjectionTargetinjectionTarget=beanManager.createInjectionTarget(annotationType);
CreationalContextcreationalContext=beanManager.createCreationalContext(null);
injectionTarget.inject(t,creationalContext);
injectionTarget.postConstruct(t);
returnt;
}
JAVA
@SvenRuppert 105/122
CDI explained by code 5 / 7
CDI managed DynamicObjectAdapter - besserer Decorator
public class DemoLogicProducer {
@Inject Instance<DynamicObjectAdapterFactory> dOAFInstance;
@Inject Context context;
@Produces @DynamicDecoratorTest
public DemoLogic create(ManagedInstanceCreator instanceCreator){
final DemoLogic demoLogic = instanceCreator.activateCDI(new DemoLogic() {});
final DynamicObjectAdapterFactory dynamicObjectAdapterFactory = dOAFInstance.get();
final Object adapter;
if (context.original){ adapter = new Object(); }
else { //kann hier beliebig komplex werden
adapter = instanceCreator.activateCDI(new DemoLogicAdapter_A());
}
//hier interface notwendig... see insight
return dynamicObjectAdapterFactory.adapt(demoLogic, DemoLogic.class, adapter);
}
JAVA
@SvenRuppert 106/122
CDI explained by code 6 / 7
CDI managed DynamicObjectAdapter - besserer Decorator
publicclassDynamicObjectAdapterFactory{
@InjectInstance<CDIInvocationHandler>cdiInvocationHandlerInstance;
public<T>Tadapt(finalObjectadaptee,finalClass<T>target,finalObjectadapter){
finalCDIInvocationHandlerinvocationHandler=
cdiInvocationHandlerInstance.get().adapter(adapter).adaptee(adaptee);
return(T)Proxy.newProxyInstance(
target.getClassLoader(),
newClass[]{target}, //hierInterfacenotwendig!
invocationHandler
);
}
}
JAVA
@SvenRuppert 107/122
CDI explained by code 7a / 7c
CDI managed DynamicObjectAdapter - besserer Decorator
publicclassMethodIdentifier{
privatefinalStringname;
privatefinalClass[]parameters;
publicMethodIdentifier(Methodm){
name=m.getName();parameters=m.getParameterTypes();
}
//wecansavetimebyassumingthatweonlycompareagainst
//otherMethodIdentifierobjects
publicbooleanequals(Objecto){
MethodIdentifiermid=(MethodIdentifier)o;
returnname.equals(mid.name)&&Arrays.equals(parameters,mid.parameters);
}
publicinthashCode(){ returnname.hashCode();}
}
JAVA
@SvenRuppert 108/122
CDI explained by code 7b / 7c
CDI managed DynamicObjectAdapter - besserer Decorator
publicclassCDIInvocationHandlerimplementsInvocationHandler{
privateMap<MethodIdentifier,Method>adaptedMethods=newHashMap<>();
privateObjectadapter;privateObjectadaptee;
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
if(adaptedMethods.isEmpty()){
Method[]methods=adapter.getClass().getDeclaredMethods();
for(Methodm:methods){ adaptedMethods.put(newMethodIdentifier(m),m);}
}
try{
Methodother=adaptedMethods.get(newMethodIdentifier(method));
if(other!=null) {returnother.invoke(adapter,args);}
else {returnmethod.invoke(adaptee,args); }
}catch(InvocationTargetExceptione){throwe.getTargetException();}
}...
JAVA
@SvenRuppert 109/122
CDI explained by code 7c / 7c
CDI managed DynamicObjectAdapter - besserer Decorator
Mit diesem Pattern sind wir in der Lage die Unzulänglichkeiten des CDI
Decorators auszugleichen.
@SvenRuppert 110/122
CDI explained by code 7c / 7c
CDI managed DynamicObjectAdapter - besserer Decorator
Mit diesem Pattern sind wir in der Lage die Unzulänglichkeiten des CDI
Decorators auszugleichen.
Spätere Änderungen an dem Interface führen nicht dazu, dass alle Adapter
angepasst werden müssen
@SvenRuppert 111/122
CDI explained by code 7c / 7c
CDI managed DynamicObjectAdapter - besserer Decorator
Mit diesem Pattern sind wir in der Lage die Unzulänglichkeiten des CDI
Decorators auszugleichen.
Spätere Änderungen an dem Interface führen nicht dazu, dass alle Adapter
angepasst werden müssen
Alle Komponenten sind von dem verwendeten CDI-Container verwaltet
@SvenRuppert 112/122
Cross Language Injection
.. am Beispiel von Kotlin..
classDemoLogicKotlin(){
publicfunworkOnString():String{
return"DemoLogicKotlin"
}
}
JAVA
@SvenRuppert 113/122
Cross Language Injection
.. am Beispiel von Kotlin..
entweder : Adapter mit Delegator
@CDINotMapped
publicclassDemoLogicKotlinWrapperimplementsDemoLogic{
private@InjectDemoLogicKotlinkotlin;
publicStringworkOnString(){
returnkotlin.workOnString();
}
}
JAVA
@SvenRuppert 114/122
Cross Language Injection
.. am Beispiel von Kotlin..
oder mittels Producer direkt verfügbar machen
@CDINotMapped
publicclassDemoLogicKotlinProducer{
@InjectManagedInstanceCreatorcreator;
//@InjectDemoLogicKotlinkotlin;
@Produces@KotlinImpl
publicDemoLogiccreate(){
finalDemoLogiclogic=newDemoLogicKotlinWrapper();
returncreator.activateCDI(logic);
}
}
JAVA
@SvenRuppert 115/122
CDI und TDD
... kaskadierte MOCKS
Service A injected Service B injected Service C
@SvenRuppert 116/122
CDI und TDD
... kaskadierte MOCKS
Service A injected Service B injected Service C
Service A (mocked) injected Service B injected Service C
@SvenRuppert 117/122
CDI und TDD
... kaskadierte MOCKS
Service A injected Service B injected Service C
Service A (mocked) injected Service B injected Service C
Service A injected Service B (mocked) injected Service C
@SvenRuppert 118/122
CDI und TDD
... kaskadierte MOCKS
Service A injected Service B injected Service C
Service A (mocked) injected Service B injected Service C
Service A injected Service B (mocked) injected Service C
Service A (mocked) injected Service B (mocked) injected Service C
@SvenRuppert 119/122
CDI und TDD
... kaskadierte MOCKS
Service A injected Service B injected Service C
Service A (mocked) injected Service B injected Service C
Service A injected Service B (mocked) injected Service C
Service A (mocked) injected Service B (mocked) injected Service C
beliebige Kombinationen können so dynamisch zusammen geschaltet werden.
@SvenRuppert 120/122
finally at amazon..
my book with Dr, Heinz Kabutz
Book about Reflection - part one
Dynamic Proxies z.B. ...dynamic static proxies... ;-)
<Thank You!>
g+ www.google.com/+SvenRuppert
twitter @SvenRuppert
www www.rapidpm.org
www www.rapidpm.org
github github.com/svenruppert

Warum ich so auf das c von cdi stehe

  • 1.
    Warum CDI oder gibtes einen tieferen Sinn dahinter? warum denn CDI ? ;-)
  • 2.
    @SvenRuppert 4/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? oft gehörte Antwort kürzere Notation.. *oje* Manchmal ist die Notation per Inject kürzer. Sobald allerdings die einzelnen Qualifier dazukommen, ist meist der Aufwand zum Aufruf eines Konstruktors kaum unterschiedlich. Verkürzen der Notation ist natürlich nicht das Ziel von CDI
  • 3.
    @SvenRuppert 5/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? lösen/entfernen von statischen Abhängigkeiten
  • 4.
    @SvenRuppert 6/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? lösen/entfernen von statischen Abhängigkeiten Dieser Punkt ist einer der wesentlichen. Also: Wie kann man zur Entwicklungszeit die Abhängigkeiten zu den anderen Projektmodulen möglichst gering halten?
  • 5.
    @SvenRuppert 7/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? lösen/entfernen von statischen Abhängigkeiten Dieser Punkt ist einer der wesentlichen. Also: Wie kann man zur Entwicklungszeit die Abhängigkeiten zu den anderen Projektmodulen möglichst gering halten? Gehen wir von der Definition einer Liste aus. Als Rückgabewert einer Methode wird eine Instanz der Implementierung von List verwendet. publicList<Data>execute(){...}; JAVA
  • 6.
    @SvenRuppert 8/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Damit sind nachfolgende Aufrufer nicht mehr an die Implementierung der List gebunden. importjava.util.List; importjava.util.ArrayList; publicList<Data>execute(){ finalList<Data>result=newArrayList<>(); //.... returnresult; } JAVA
  • 7.
    @SvenRuppert 9/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Damit sind nachfolgende Aufrufer nicht mehr an die Implementierung der List gebunden. In der Methode jedoch besteht meist die Abhängigkeit zu der entsprechenden Implementierung obwohl auch das meist nicht notwendig ist. importjava.util.List; importjava.util.ArrayList; publicList<Data>execute(){ finalList<Data>result=newArrayList<>(); //.... returnresult; } JAVA
  • 8.
    @SvenRuppert 10/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet.
  • 9.
    @SvenRuppert 11/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet. Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig.
  • 10.
    @SvenRuppert 12/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet. Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig. Sollte sich zur Laufzeit herausstellen, das die Wahl dieser Implementierung nicht optimal gewesen ist, muss der Quelltext angepasst und neu verteilt werden.
  • 11.
    @SvenRuppert 13/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet. Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig. Sollte sich zur Laufzeit herausstellen, das die Wahl dieser Implementierung nicht optimal gewesen ist, muss der Quelltext angepasst und neu verteilt werden. z.B. Mit std SE Mitteln kann man das durch entsprechende Factories lösen.
  • 12.
    @SvenRuppert 14/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Mit std SE Mitteln kann man das durch entsprechende Factories lösen. Beispielhaft soll hier folgende Implementierung verwendet werden. importjava.util.ArrayList; importjava.util.LinkedList; importjava.util.List; publicclassListFactory{ publicListcreateArrayList() {returnnewArrayList();} publicListcreateLinkedList(){returnnewLinkedList();} publicListcreateList() {returnnewArrayList();} } JAVA
  • 13.
    @SvenRuppert 15/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Haben wir damit etwas erreicht?
  • 14.
    @SvenRuppert 16/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Haben wir damit etwas erreicht? ... bzw was haben wir damit erreicht?
  • 15.
    @SvenRuppert 17/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Haben wir damit etwas erreicht? ... bzw was haben wir damit erreicht? z.B. Die Entwickler verwenden nun diese Factory.
  • 16.
    @SvenRuppert 18/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Haben wir damit etwas erreicht? ... bzw was haben wir damit erreicht? z.B. Die Entwickler verwenden nun diese Factory. -> wenn sie wissen das es diese gibt! ;-)
  • 17.
    @SvenRuppert 19/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Vorher / Nachher (1/2) importjava.util.List; importjava.util.ArrayList; publicList<Data>execute(){ finalList<Data>result=newArrayList<>(); //.... returnresult; } JAVA
  • 18.
    @SvenRuppert 20/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Vorher / Nachher (2/2) importjava.util.List; importjava.util.ArrayList; publicList<Data>execute(){ finalList<Data>result=newArrayList<>(); //.... returnresult; } importjava.util.List; importorg.rapidpm.demo.ListFactory; publicList<Data>execute(){ finalListlist=newListFactory().createArrayList(); //.... returnresult; } JAVA
  • 19.
    @SvenRuppert 21/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
  • 20.
    @SvenRuppert 22/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert. Die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch explizit gefallen.
  • 21.
    @SvenRuppert 23/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert. Die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch explizit gefallen. Die Abhängigkeit zur Factory wurde hinzugefügt.
  • 22.
    @SvenRuppert 24/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert. Die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch explizit gefallen. Die Abhängigkeit zur Factory wurde hinzugefügt. Die Implementierung der ListFactory selber hat auch wieder die statischen Abhängigkeiten zu allen vorgesehenen Implementierungen.
  • 23.
    @SvenRuppert 25/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen Implementierungen
  • 24.
    @SvenRuppert 26/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen Implementierungen Anforderung Nr 2: keine statischen Entscheidungen für spezifische Implementierungen
  • 25.
    @SvenRuppert 27/122 Warum CDIoder gibt es einen tieferen Sinn dahinter? Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen Implementierungen Anforderung Nr 2: keine statischen Entscheidungen für spezifische Implementierungen Was ist jetzt eine mögliche Lösung ???
  • 26.
    @SvenRuppert 28/122 Lösungsversuch Nr1 basierend auf Java SE Eine etwas dynamischere Lösung...
  • 27.
    @SvenRuppert 29/122 Lösungsversuch Nr1 basierend auf Java SE Eine etwas dynamischere Lösung... importjava.util.ArrayList; importjava.util.LinkedList; importjava.util.List; importorg.rapidpm.demo.cdi.commons.registry.ContextResolver; publicclassListFactory{ publicListcreateList(finalContextResolvercontextResolver){ if(contextResolver==null){returncreateArrayList();} else{ if(contextResolver.resolveContext()){returncreateArrayList();} else{returncreateLinkedList();} } } } JAVA
  • 28.
    @SvenRuppert 30/122 Lösungsversuch Nr1 basierend auf Java SE Eine etwas dynamischere Lösung... Die Komplexität der Entscheidung liegt nun im ContextResolver
  • 29.
    @SvenRuppert 31/122 Lösungsversuch Nr1 basierend auf Java SE Eine etwas dynamischere Lösung... Die Komplexität der Entscheidung liegt nun im ContextResolver Abhängigkeit in der Factory zum ContextResolver hinzugefügt
  • 30.
    @SvenRuppert 32/122 Lösungsversuch Nr1 basierend auf Java SE Eine etwas dynamischere Lösung... Die Komplexität der Entscheidung liegt nun im ContextResolver Abhängigkeit in der Factory zum ContextResolver hinzugefügt Gewonnen: zur Laufzeit sich für eine Implementierung entscheiden.
  • 31.
    @SvenRuppert 33/122 Lösungsversuch Nr1 basierend auf Java SE Möchte man nun die Factory so erstellen, dass diese wiederum keine statischen Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste hat, muss eine z.B. Registry gebaut werden.
  • 32.
    @SvenRuppert 34/122 Lösungsversuch Nr1 basierend auf Java SE Möchte man nun die Factory so erstellen, dass diese wiederum keine statischen Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste hat, muss eine z.B. Registry gebaut werden. Dort kann man zur Laufzeit die jeweiligen Implementierungen registrieren und für eine Auflösung zur Verfügung stellen.
  • 33.
    @SvenRuppert 35/122 Lösungsversuch Nr1 basierend auf Java SE Möchte man nun die Factory so erstellen, dass diese wiederum keine statischen Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste hat, muss eine z.B. Registry gebaut werden. Dort kann man zur Laufzeit die jeweiligen Implementierungen registrieren und für eine Auflösung zur Verfügung stellen. Hier hilft CDI durch seine Konzepte, ohne das man sich mit der Basisimplementierung der Infrastruktur beschäftigen muss.
  • 34.
    @SvenRuppert 36/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt
  • 35.
    @SvenRuppert 37/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt @InjectListlist; JAVA
  • 36.
    @SvenRuppert 38/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt @Inject@CDILegacyTestListlist; JAVA
  • 37.
    @SvenRuppert 39/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt @Inject@CDILegacyTestListlist; @Produces@CDILegacyTest publicListcreateList(...){...} JAVA
  • 38.
    @SvenRuppert 40/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt @Inject@CDILegacyTestListlist; @Produces@CDILegacyTest publicListcreateList(InjectionPointinjectionPoint, BeanManagerbeanManager,ContextResolvercontextResolver){ .... } JAVA
  • 39.
    @SvenRuppert 41/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt @Inject@CDILegacyTestListlist; @Produces@CDILegacyTest publicListcreateList(InjectionPointinjectionPoint, BeanManagerbeanManager,ContextResolvercontextResolver){ booleanb=contextResolver.resolveContext(...); //treffenderEntscheidungen... if(b){returnnewLinkedList();}else{returnnewArrayList();} } JAVA
  • 40.
    @SvenRuppert 42/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt Aber leider ist das immer noch zu dem Zeitpunkt zu dem die umliegende Instanz erzeugt wird. @Inject@CDILegacyTestListlist; @Produces@CDILegacyTest publicListcreateList(InjectionPointinjectionPoint, BeanManagerbeanManager,ContextResolvercontextResolver){ booleanb=contextResolver.resolveContext(...); //treffenderEntscheidungen... if(b){returnnewLinkedList();}else{returnnewArrayList();} } JAVA
  • 41.
    @SvenRuppert 43/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden.
  • 42.
    @SvenRuppert 44/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden. Damit sind späte Entscheidungen möglich
  • 43.
    @SvenRuppert 45/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden. Damit sind späte Entscheidungen möglich @Inject@CDILegacyTestInstance<List>listInstance; JAVA
  • 44.
    @SvenRuppert 46/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden. Damit sind späte Entscheidungen möglich @Inject@CDILegacyTestInstance<List>listInstance; //..später finalListlist=listInstance.get(); JAVA
  • 45.
    @SvenRuppert 47/122 endlich CDI;-) basierend auf Weld / WELD-SE Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden damit sind späte Entscheidungen möglich @Inject@CDILegacyTestInstance<List>listInstance; //..später finalListlist=listInstance.get(); @Produces@CDILegacyTest publicListcreateList(InjectionPointinjectionPoint, BeanManagerbeanManager,ContextResolvercontextResolver){ booleanb=contextResolver.resolveContext(...); //treffenderEntscheidungen... if(b){returnnewLinkedList();}else{returnnewArrayList();} } JAVA
  • 46.
    @SvenRuppert 48/122 CDI was wurdebis jetzt erreicht? Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der Vererbung
  • 47.
    @SvenRuppert 49/122 CDI was wurdebis jetzt erreicht? Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der Vererbung Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt
  • 48.
    @SvenRuppert 50/122 CDI was wurdebis jetzt erreicht? Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der Vererbung Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt Für jede Entscheidung einen Producer
  • 49.
    @SvenRuppert 51/122 CDI was wurdebis jetzt erreicht? Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der Vererbung Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt Für jede Entscheidung einen Producer.. wie funktioniert das praktisch?
  • 50.
    @SvenRuppert 52/122 CDI was wurdebis jetzt erreicht? Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der Vererbung Keine "allwissende" Factory, die alle statischen Abhängigkeiten besitzt Für jede Entscheidung einen Producer.. wie funktioniert das praktisch? ... sehen wir uns gleich noch an.... Bitte ein wenig Geduld...
  • 51.
    @SvenRuppert 53/122 CDI was wurdedafür in Kauf genommen? statische Kopplung über AnnotationsLiterale: @Inject@MyQualifierListliste; JAVA
  • 52.
    @SvenRuppert 54/122 CDI was wurdedafür in Kauf genommen? statische Kopplung über AnnotationsLiterale: schlechterer Umgang mit Generics @Inject@MyQualifierListliste; JAVA
  • 53.
    @SvenRuppert 55/122 CDI was wurdedafür in Kauf genommen? statische Kopplung über AnnotationsLiterale: schlechterer Umgang mit Generics keine Komplexitätsreduktion für den Entwickler @Inject@MyQualifierListliste; JAVA
  • 54.
    @SvenRuppert 56/122 CDI explainedby code HelloLogger zum aufwärmen/wiederholen klassischer Fall, Logger im System @Inject@CDILoggerLoggerlogger; JAVA
  • 55.
    @SvenRuppert 57/122 CDI explainedby code HelloLogger zum aufwärmen/wiederholen klassischer Fall, Logger im System @Inject@CDILoggerLoggerlogger; @Qualifier @Retention(value=RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) public@interfaceCDILogger{} JAVA
  • 56.
    @SvenRuppert 58/122 CDI explainedby code HelloLogger zum aufwärmen/wiederholen klassischer Fall, Logger im System @Inject@CDILoggerLoggerlogger; @Qualifier @Retention(value=RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) public@interfaceCDILogger{} @Produces@CDILogger publicLoggerproduceLog4JLogger(InjectionPointiP,BeanManagerbeanManager){ finalClass<?>declaringClass=iP.getMember().getDeclaringClass(); returnnewLogger(declaringClass); } JAVA
  • 57.
    @SvenRuppert 59/122 CDI explainedby code HelloLogger zum aufwärmen/wiederholen klassischer Fall, Logger im System @Inject@CDILoggerLoggerlogger; @Qualifier @Retention(value=RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) public@interfaceCDILogger{} @Produces@CDILogger publicLoggerproduceLog4JLogger(InjectionPointiP,BeanManagerbeanManager){ finalClass<?>declaringClass=iP.getMember().getDeclaringClass(); returnnewLogger(declaringClass);//Loggernichtgemanaged!!! } JAVA
  • 58.
    @SvenRuppert 60/122 CDI explainedby code HelloLogger zum aufwärmen / Hat uns das jetzt richtig weitergebracht? Referenz auf Factory wird ersetzt durch Qualifier. :-( @Inject@CDILoggerLoggerlogger; JAVA
  • 59.
    @SvenRuppert 61/122 CDI explainedby code HelloLogger zum aufwärmen / Hat uns das jetzt richtig weitergebracht? Referenz auf Factory wird ersetzt durch Qualifier. :-( Spezifische Producer losgelöst von den anderen Producern @Inject@CDILoggerLoggerlogger; JAVA
  • 60.
    @SvenRuppert 62/122 CDI explainedby code HelloLogger zum aufwärmen / Hat uns das jetzt richtig weitergebracht? Referenz auf Factory wird ersetzt durch Qualifier. :-( Spezifische Producer losgelöst von den anderen Producern zentrale Stelle für context-bezogene Entscheidungen @Inject@CDILoggerLoggerlogger; JAVA
  • 61.
    @SvenRuppert 63/122 CDI explainedby code Qualifier und AnnotationsLiterale @Inject@CDILoggerLoggerlogger; JAVA
  • 62.
    @SvenRuppert 64/122 CDI explainedby code Qualifier und AnnotationsLiterale @Inject@CDILoggerLoggerlogger; JAVA @Producer@CDILoggerLoggercreate(...); JAVA
  • 63.
    @SvenRuppert 65/122 CDI explainedby code Qualifier und AnnotationsLiterale @Inject@CDILoggerLoggerlogger; JAVA @Producer@CDILoggerLoggercreate(...); JAVA @Producer@CDILoggerLoggercreate(..){ AnnotationsLiteral<T>prodAL=contextResolver.resolve(..); }; JAVA
  • 64.
    @SvenRuppert 66/122 CDI explainedby code Qualifier und AnnotationsLiterale @Inject@CDILoggerLoggerlogger; JAVA @Producer@CDILoggerLoggercreate(...); JAVA @Producer@CDILoggerLoggercreate(BeanManagerbm,ContextResolvercr){ AnnotationsLiteral<T>prodAL=contextResolver.resolve(..); returncreator.getManagedInstance(Logger.class,annotationLiteral); }; JAVA
  • 65.
    @SvenRuppert 67/122 CDI explainedby code Qualifier und AnnotationsLiterale Es wird dynamisch auf ein AnnotationsLiteral aufgelöst. @Inject@CDILoggerLoggerlogger; JAVA @Producer@CDILoggerLoggercreate(...); JAVA @Producer@CDILoggerLoggercreate(BeanManagerbm,ContextResolvercr){ AnnotationsLiteral<T>prodAL=contextResolver.resolve(..); returncreator.getManagedInstance(Logger.class,annotationLiteral); }; JAVA
  • 66.
    @SvenRuppert 68/122 CDI explainedby code Qualifier und AnnotationsLiterale Es wird dynamisch auf ein AnnotationsLiteral aufgelöst. AnnotationsLiteral und Klasse -> Auswahl des Producers @Inject@CDILoggerLoggerlogger; JAVA @Producer@CDILoggerLoggercreate(...); JAVA @Producer@CDILoggerLoggercreate(BeanManagerbm,ContextResolvercr){ AnnotationsLiteral<T>prodAL=contextResolver.resolve(..); returncreator.getManagedInstance(Logger.class,annotationLiteral); }; JAVA
  • 67.
    @SvenRuppert 69/122 CDI explainedby code 1 / 6 ContextResolver / aus der Sicht des Entwicklers @InjectCDIContextcontext;//z.B.einSingleton @InjectContextResolvercr; @Test publicvoidtestMockedModus001()throwsException{ Assert.assertFalse(context.isMockedModusActive()); finalAnnotationLiteralannotationLiteralProd=cr.resolveContext(this.getClass()); Assert.assertEquals(newAnnotationLiteral<CDICommons>(){},annotationLiteralProd); } JAVA
  • 68.
    @SvenRuppert 70/122 CDI explainedby code 1 / 6 ContextResolver / aus der Sicht des Entwicklers @InjectCDIContextcontext;//z.B.einSingleton @InjectContextResolvercr; @Test publicvoidtestMockedModus001()throwsException{ Assert.assertFalse(context.isMockedModusActive()); finalAnnotationLiteralannotationLiteralProd=cr.resolveContext(this.getClass()); Assert.assertEquals(newAnnotationLiteral<CDICommons>(){},annotationLiteralProd); ((TestContext)context).setTestModus(true); Assert.assertTrue(context.isMockedModusActive()); } JAVA
  • 69.
    @SvenRuppert 71/122 CDI explainedby code 1 / 6 ContextResolver / aus der Sicht des Entwicklers @InjectCDIContextcontext;//z.B.einSingleton @InjectContextResolvercr; @Test publicvoidtestMockedModus001()throwsException{ Assert.assertFalse(context.isMockedModusActive()); finalAnnotationLiteralannotationLiteralProd=cr.resolveContext(this.getClass()); Assert.assertEquals(newAnnotationLiteral<CDICommons>(){},annotationLiteralProd); ((TestContext)context).setTestModus(true); Assert.assertTrue(context.isMockedModusActive()); finalAnnotationLiteralannotationLiteral=cr.resolveContext(this.getClass()); Assert.assertEquals(newAnnotationLiteral<CDICommonsMocked>(){},annotationLiteral); } JAVA
  • 70.
    @SvenRuppert 72/122 CDI explainedby code 1 / 6 ContextResolver / aus der Sicht des Entwicklers
  • 71.
    @SvenRuppert 73/122 CDI explainedby code 1 / 6 ContextResolver / aus der Sicht des Entwicklers
  • 72.
    @SvenRuppert 74/122 CDI explainedby code 2a / 6 ContextResolver Die Annotation mit @CDINotMapped, um das Interface explizit in den Namensraum zu setzen @CDINotMapped publicinterfaceCDIContext{ publicbooleanisMockedModusActive(); } JAVA
  • 73.
    @SvenRuppert 75/122 CDI explainedby code 2b / 6 ContextResolver Mit klassischen Interzeptoren kann man Querschnittsthemen deklarieren. Nur allgemein umschalten auf Mocked/NotMocked möglich? @InterceptorBinding @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(value=RetentionPolicy.RUNTIME) @Inherited public@interfaceCheckMockedContext{} publicinterfaceContextResolver{ @CheckMockedContext publicAnnotationLiteralresolveContext(finalClass<?>targetClass); } JAVA
  • 74.
    @SvenRuppert 76/122 CDI explainedby code 3a / 6 ContextResolver @Interceptor@CheckMockedContext publicclassMockedInterceptorimplementsSerializable{ @InjectCDIContextcontext; private@Inject@CDILoggerLoggerlogger; @AroundInvoke publicObjectcheckMockedMode(InvocationContextctx)throwsException{ if(context.isMockedModusActive()){ if(logger.isDebugEnabled()){logger.debug("MockedModusactive");} returnnewAnnotationLiteral<CDICommonsMocked>(){}; }else{ returnctx.proceed(); } } } JAVA
  • 75.
    @SvenRuppert 77/122 CDI explainedby code 3b / 6 ContextResolver Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar
  • 76.
    @SvenRuppert 78/122 CDI explainedby code 3b / 6 ContextResolver Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar Benötigt wird aber evtl differenziertes Umschalten.
  • 77.
    @SvenRuppert 79/122 CDI explainedby code 3b / 6 ContextResolver Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar Benötigt wird aber evtl differenziertes Umschalten. Interzeptoren werden statisch definiert - schade....
  • 78.
    @SvenRuppert 80/122 CDI explainedby code 4a / 6 ContextResolver @CDICommons public class DefaultContextResolver implements ContextResolver { @Inject @CDILogger Logger logger; @Inject BeanManager beanManager; public Set<ContextResolver> gettAllContextResolver() { final Set<ContextResolver> resultSet = new HashSet<>(); final Set<Bean<?>> allBeans = beanManager .getBeans(ContextResolver.class, new AnnotationLiteral<Any>() {}); allBeans.forEach(b-> b.getTypes().stream() .filter(t -> t.equals(ContextResolver.class)) .filter(r -> !r.getClass().isAnnotationPresent(CDICommonsMocked.class)) .forEach(t -> { final ContextResolver cr = ((Bean<ContextResolver>) b) .create(beanManager.createCreationalContext((Bean<ContextResolver>) b)); resultSet.add(cr); })); return resultSet; } JAVA
  • 79.
    @SvenRuppert 81/122 CDI explainedby code 4b / 6 ContextResolver publicSet<ContextResolver>gettAllMockedContextResolver(){ finalSet<ContextResolver>resultSet=newHashSet<>(); finalSet<Bean<?>>allBeans=beanManager .getBeans(ContextResolver.class,newAnnotationLiteral<CDICommonsMocked>(){}); allBeans.forEach(b->b.getTypes().forEach(type->{ if(type.equals(ContextResolver.class)){ finalContextResolvert=((Bean<ContextResolver>)b) .create(beanManager.createCreationalContext((Bean<ContextResolver>)b)); resultSet.add(t); } })); returnresultSet; } JAVA
  • 80.
    @SvenRuppert 82/122 CDI explainedby code 4c / 6 ContextResolver publicAnnotationLiteralresolveContext(ClasstargetClass){ Stream<ContextResolver>contextResolversMocked=gettAllMockedContextResolver().stream(); Stream<ContextResolver>contextResolvers=gettAllContextResolver().stream(); returncontextResolversMocked .filter(r->(r.resolveContext(targetClass)!=null)) .map(r->r.resolveContext(targetClass)) .findFirst().orElse( contextResolvers .filter(r->!r.getClass().isAnnotationPresent(CDICommonsMocked.class)) .filter(r->!r.getClass().equals(DefaultContextResolver.class)) .filter(r->(r.resolveContext(targetClass)!=null)) .map(r->r.resolveContext(targetClass)) .findFirst().orElse(null) ); } JAVA
  • 81.
    @SvenRuppert 83/122 CDI explainedby code 5 / 6 ContextResolver @Singleton publicclassTestContextimplementsCDIContext{ privatebooleantestModus=false; @OverridepublicbooleanisMockedModusActive(){returntestModus;} publicbooleanisTestModus(){returntestModus;} publicvoidsetTestModus(booleantestModus){this.testModus=testModus;} } publicclassTestContextResolverimplementsContextResolver{ @InjectCDIContextcontext; @CheckMockedContext @OverridepublicAnnotationLiteralresolveContext(Class<?>targetClass){ //entscheideobDuzuständigbist returnnewAnnotationLiteral<CDICommons>(){}; } } JAVA
  • 82.
    @SvenRuppert 84/122 CDI explainedby code 6 / 6 ContextResolver Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren.
  • 83.
    @SvenRuppert 85/122 CDI explainedby code 6 / 6 ContextResolver Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren. ContextResolver sind immer nur in ihrem fachlichen Bereich aktiv
  • 84.
    @SvenRuppert 86/122 CDI explainedby code 6 / 6 ContextResolver Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren. ContextResolver sind immer nur in ihrem fachlichen Bereich aktiv Unterscheidung auf z.B. Mandantenebene leicht realisierbar
  • 85.
    @SvenRuppert 87/122 CDI explainedby code 1 / 7 CDI managed DynamicObjectAdapter - besserer Decorator klassischer Decorator in CDI @Decorator publicabstractclassCoderDecoratorimplementsCoder{ @Inject@Delegate@AnyCodercoder; publicStringcodeString(Strings,inttval){ intlen=s.length(); return"""+s+""becomes"+"""+coder.codeString(s,tval) +"","+len+"charactersinlength"; } } Insidebeans.xml <decorators> <class>decorators.CoderDecorator</class> </decorators> JAVA
  • 86.
    @SvenRuppert 88/122 CDI explainedby code 2 / 7 CDI managed DynamicObjectAdapter - der bessere Decorator Ein Decorator in CDI muss in der beans.xml definiert werden.
  • 87.
    @SvenRuppert 89/122 CDI explainedby code 2 / 7 CDI managed DynamicObjectAdapter - der bessere Decorator Ein Decorator in CDI muss in der beans.xml definiert werden. Klasse mit einer speziellen Annotation @Decorator
  • 88.
    @SvenRuppert 90/122 CDI explainedby code 2 / 7 CDI managed DynamicObjectAdapter - der bessere Decorator Ein Decorator in CDI muss in der beans.xml definiert werden. Klasse mit einer speziellen Annotation @Decorator Innerhalb des Decorators muss die Instanz des Originals injiziert werden
  • 89.
    @SvenRuppert 91/122 CDI explainedby code 2 / 7 CDI managed DynamicObjectAdapter - der bessere Decorator Ein Decorator in CDI muss in der beans.xml definiert werden. Klasse mit einer speziellen Annotation @Decorator Innerhalb des Decorators muss die Instanz des Originals injiziert werden Decorator muss von der Original-Implementierung oder dem Interface ableiten
  • 90.
    @SvenRuppert 92/122 CDI explainedby code 2 / 7 CDI managed DynamicObjectAdapter - der bessere Decorator Ein Decorator in CDI muss in der beans.xml definiert werden. Klasse mit einer speziellen Annotation @Decorator Innerhalb des Decorators muss die Instanz des Originals injiziert werden Decorator muss von der Original-Implementierung oder dem Interface ableiten ... geht das auch schöner ?
  • 91.
    @SvenRuppert 93/122 CDI explainedby code 3 / 7 CDI managed DynamicObjectAdapter - der bessere Decorator Aus der Sicht des Entwicklers @CDINotMapped publicinterfaceDemoLogic{ publicdefaultintadd(inta,intb){ returna+b;} publicdefaultintsub(inta,intb){ returna-b;} } @CDINotMapped publicclassDemoLogicAdapter_AimplementsDemoLogic{ publicintadd(inta,intb){ returna+b+100; } } @Singleton //sollteschonbekanntsein;-) publicclassContext{publicbooleanoriginal=true;} JAVA
  • 92.
    @SvenRuppert 94/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic
  • 93.
    @SvenRuppert 95/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic
  • 94.
    @SvenRuppert 96/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1)
  • 95.
    @SvenRuppert 97/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2.
  • 96.
    @SvenRuppert 98/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2. Context-Switch auf mandantenabhängige Implementierung
  • 97.
    @SvenRuppert 99/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2. Context-Switch auf mandantenabhängige Implementierung Holen einer Instanz der DemoLogic
  • 98.
    @SvenRuppert 100/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2. Context-Switch auf mandantenabhängige Implementierung Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1)
  • 99.
    @SvenRuppert 101/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2. Context-Switch auf mandantenabhängige Implementierung Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 102.
  • 100.
    @SvenRuppert 102/122 CDI explainedby code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 2. Context-Switch auf mandantenabhängige Implementierung Holen einer Instanz der DemoLogic Aufruf der Methode add(1,1) Überprüfung ob das Ergebnis den Erwartungen entspricht, hier der Wert 102. Kaffee trinken.
  • 101.
    @SvenRuppert 103/122 CDI explainedby code 4b / 7 CDI managed DynamicObjectAdapter - besserer Decorator @Inject@DynamicDecoratorTestInstance<DemoLogic>demoLogic; @InjectContextcontext; @Test publicvoidtestDemoLogicOriginalTest()throwsException{ Assert.assertNotNull(demoLogic); finalDemoLogicdemoLogic1=demoLogic.get(); finalintadd=demoLogic1.add(1,1); Assert.assertEquals(2,add); System.out.println("add="+add); context.original=false; finalDemoLogicdemoLogic2=demoLogic.get(); finalintaddAdapted=demoLogic2.add(1,1); Assert.assertEquals(102,addAdapted); System.out.println("addAdapted="+addAdapted); } JAVA
  • 102.
    @SvenRuppert 104/122 CDI explainedby code 4c / 7 CDI managed DynamicObjectAdapter - besserer Decorator manuelles aktivieren von CDI.. yepp das geht public<T>TactivateCDI(Tt){ finalClassaClass=t.getClass(); if(logger.isDebugEnabled()){logger.debug("activateCDI->"+aClass);} AnnotatedTypeannotationType=beanManager.createAnnotatedType(aClass); InjectionTargetinjectionTarget=beanManager.createInjectionTarget(annotationType); CreationalContextcreationalContext=beanManager.createCreationalContext(null); injectionTarget.inject(t,creationalContext); injectionTarget.postConstruct(t); returnt; } JAVA
  • 103.
    @SvenRuppert 105/122 CDI explainedby code 5 / 7 CDI managed DynamicObjectAdapter - besserer Decorator public class DemoLogicProducer { @Inject Instance<DynamicObjectAdapterFactory> dOAFInstance; @Inject Context context; @Produces @DynamicDecoratorTest public DemoLogic create(ManagedInstanceCreator instanceCreator){ final DemoLogic demoLogic = instanceCreator.activateCDI(new DemoLogic() {}); final DynamicObjectAdapterFactory dynamicObjectAdapterFactory = dOAFInstance.get(); final Object adapter; if (context.original){ adapter = new Object(); } else { //kann hier beliebig komplex werden adapter = instanceCreator.activateCDI(new DemoLogicAdapter_A()); } //hier interface notwendig... see insight return dynamicObjectAdapterFactory.adapt(demoLogic, DemoLogic.class, adapter); } JAVA
  • 104.
    @SvenRuppert 106/122 CDI explainedby code 6 / 7 CDI managed DynamicObjectAdapter - besserer Decorator publicclassDynamicObjectAdapterFactory{ @InjectInstance<CDIInvocationHandler>cdiInvocationHandlerInstance; public<T>Tadapt(finalObjectadaptee,finalClass<T>target,finalObjectadapter){ finalCDIInvocationHandlerinvocationHandler= cdiInvocationHandlerInstance.get().adapter(adapter).adaptee(adaptee); return(T)Proxy.newProxyInstance( target.getClassLoader(), newClass[]{target}, //hierInterfacenotwendig! invocationHandler ); } } JAVA
  • 105.
    @SvenRuppert 107/122 CDI explainedby code 7a / 7c CDI managed DynamicObjectAdapter - besserer Decorator publicclassMethodIdentifier{ privatefinalStringname; privatefinalClass[]parameters; publicMethodIdentifier(Methodm){ name=m.getName();parameters=m.getParameterTypes(); } //wecansavetimebyassumingthatweonlycompareagainst //otherMethodIdentifierobjects publicbooleanequals(Objecto){ MethodIdentifiermid=(MethodIdentifier)o; returnname.equals(mid.name)&&Arrays.equals(parameters,mid.parameters); } publicinthashCode(){ returnname.hashCode();} } JAVA
  • 106.
    @SvenRuppert 108/122 CDI explainedby code 7b / 7c CDI managed DynamicObjectAdapter - besserer Decorator publicclassCDIInvocationHandlerimplementsInvocationHandler{ privateMap<MethodIdentifier,Method>adaptedMethods=newHashMap<>(); privateObjectadapter;privateObjectadaptee; publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ if(adaptedMethods.isEmpty()){ Method[]methods=adapter.getClass().getDeclaredMethods(); for(Methodm:methods){ adaptedMethods.put(newMethodIdentifier(m),m);} } try{ Methodother=adaptedMethods.get(newMethodIdentifier(method)); if(other!=null) {returnother.invoke(adapter,args);} else {returnmethod.invoke(adaptee,args); } }catch(InvocationTargetExceptione){throwe.getTargetException();} }... JAVA
  • 107.
    @SvenRuppert 109/122 CDI explainedby code 7c / 7c CDI managed DynamicObjectAdapter - besserer Decorator Mit diesem Pattern sind wir in der Lage die Unzulänglichkeiten des CDI Decorators auszugleichen.
  • 108.
    @SvenRuppert 110/122 CDI explainedby code 7c / 7c CDI managed DynamicObjectAdapter - besserer Decorator Mit diesem Pattern sind wir in der Lage die Unzulänglichkeiten des CDI Decorators auszugleichen. Spätere Änderungen an dem Interface führen nicht dazu, dass alle Adapter angepasst werden müssen
  • 109.
    @SvenRuppert 111/122 CDI explainedby code 7c / 7c CDI managed DynamicObjectAdapter - besserer Decorator Mit diesem Pattern sind wir in der Lage die Unzulänglichkeiten des CDI Decorators auszugleichen. Spätere Änderungen an dem Interface führen nicht dazu, dass alle Adapter angepasst werden müssen Alle Komponenten sind von dem verwendeten CDI-Container verwaltet
  • 110.
    @SvenRuppert 112/122 Cross LanguageInjection .. am Beispiel von Kotlin.. classDemoLogicKotlin(){ publicfunworkOnString():String{ return"DemoLogicKotlin" } } JAVA
  • 111.
    @SvenRuppert 113/122 Cross LanguageInjection .. am Beispiel von Kotlin.. entweder : Adapter mit Delegator @CDINotMapped publicclassDemoLogicKotlinWrapperimplementsDemoLogic{ private@InjectDemoLogicKotlinkotlin; publicStringworkOnString(){ returnkotlin.workOnString(); } } JAVA
  • 112.
    @SvenRuppert 114/122 Cross LanguageInjection .. am Beispiel von Kotlin.. oder mittels Producer direkt verfügbar machen @CDINotMapped publicclassDemoLogicKotlinProducer{ @InjectManagedInstanceCreatorcreator; //@InjectDemoLogicKotlinkotlin; @Produces@KotlinImpl publicDemoLogiccreate(){ finalDemoLogiclogic=newDemoLogicKotlinWrapper(); returncreator.activateCDI(logic); } } JAVA
  • 113.
    @SvenRuppert 115/122 CDI undTDD ... kaskadierte MOCKS Service A injected Service B injected Service C
  • 114.
    @SvenRuppert 116/122 CDI undTDD ... kaskadierte MOCKS Service A injected Service B injected Service C Service A (mocked) injected Service B injected Service C
  • 115.
    @SvenRuppert 117/122 CDI undTDD ... kaskadierte MOCKS Service A injected Service B injected Service C Service A (mocked) injected Service B injected Service C Service A injected Service B (mocked) injected Service C
  • 116.
    @SvenRuppert 118/122 CDI undTDD ... kaskadierte MOCKS Service A injected Service B injected Service C Service A (mocked) injected Service B injected Service C Service A injected Service B (mocked) injected Service C Service A (mocked) injected Service B (mocked) injected Service C
  • 117.
    @SvenRuppert 119/122 CDI undTDD ... kaskadierte MOCKS Service A injected Service B injected Service C Service A (mocked) injected Service B injected Service C Service A injected Service B (mocked) injected Service C Service A (mocked) injected Service B (mocked) injected Service C beliebige Kombinationen können so dynamisch zusammen geschaltet werden.
  • 118.
    @SvenRuppert 120/122 finally atamazon.. my book with Dr, Heinz Kabutz Book about Reflection - part one Dynamic Proxies z.B. ...dynamic static proxies... ;-)
  • 119.
  • 120.