CDI (Context Dependency Injection) ermöglicht es dem Entwickler skalierbare und flexible Architekturen aufzubauen die auf einem Java(EE) Server als auch auf dem Desktop laufen. Wie aber sollten DesignPattern aufgebaut werden unter Verwendung von CDI? Was für einen Einfluss hat Java 8 auf die DesignPattern, wie wird es mit der neuen Streams API kombiniert?
Höhepunkt ist die Kombination von klassischen Reflection-Einsatzgebieten wie z.B. dynamic Proxies mit CDI und Cross-Language Injections.
2. @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
3. @SvenRuppert 5/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
lösen/entfernen von statischen Abhängigkeiten
4. @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?
5. @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
6. @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
7. @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
8. @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.
9. @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.
10. @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.
11. @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.
12. @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
14. @SvenRuppert 16/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Haben wir damit etwas erreicht?
... bzw was haben wir damit erreicht?
15. @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.
16. @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! ;-)
17. @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
18. @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
19. @SvenRuppert 21/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
20. @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.
21. @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.
22. @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.
23. @SvenRuppert 25/122
Warum CDI oder
gibt es einen tieferen Sinn dahinter?
Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen
Implementierungen
24. @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
25. @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 ???
27. @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
28. @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
29. @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
30. @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.
31. @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.
32. @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.
33. @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.
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 wurde bis jetzt erreicht?
Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der
Vererbung
47. @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
48. @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
49. @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?
50. @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...
51. @SvenRuppert 53/122
CDI
was wurde dafür in Kauf genommen?
statische Kopplung über AnnotationsLiterale:
@Inject@MyQualifierListliste; JAVA
52. @SvenRuppert 54/122
CDI
was wurde dafür in Kauf genommen?
statische Kopplung über AnnotationsLiterale:
schlechterer Umgang mit Generics
@Inject@MyQualifierListliste; JAVA
53. @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
54. @SvenRuppert 56/122
CDI explained by code
HelloLogger zum aufwärmen/wiederholen
klassischer Fall, Logger im System
@Inject@CDILoggerLoggerlogger; JAVA
55. @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
56. @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
57. @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
58. @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
59. @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
60. @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
62. @SvenRuppert 64/122
CDI explained by code
Qualifier und AnnotationsLiterale
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
63. @SvenRuppert 65/122
CDI explained by code
Qualifier und AnnotationsLiterale
@Inject@CDILoggerLoggerlogger; JAVA
@Producer@CDILoggerLoggercreate(...); JAVA
@Producer@CDILoggerLoggercreate(..){
AnnotationsLiteral<T>prodAL=contextResolver.resolve(..);
};
JAVA
64. @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
65. @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
66. @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
67. @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
68. @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
69. @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
72. @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
73. @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
76. @SvenRuppert 78/122
CDI explained by code 3b / 6
ContextResolver
Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar
Benötigt wird aber evtl differenziertes Umschalten.
77. @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....
78. @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
82. @SvenRuppert 84/122
CDI explained by code 6 / 6
ContextResolver
Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren.
83. @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
84. @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
86. @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.
87. @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
88. @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
89. @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
90. @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 ?
91. @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
92. @SvenRuppert 94/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
93. @SvenRuppert 95/122
CDI explained by code 4a / 7
CDI managed DynamicObjectAdapter - besserer Decorator
Injizieren der Referenz auf DemoLogic
Holen einer Instanz der DemoLogic
94. @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)
95. @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.
96. @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
97. @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
98. @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)
99. @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.
100. @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.
107. @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.
108. @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
109. @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
110. @SvenRuppert 112/122
Cross Language Injection
.. am Beispiel von Kotlin..
classDemoLogicKotlin(){
publicfunworkOnString():String{
return"DemoLogicKotlin"
}
}
JAVA
111. @SvenRuppert 113/122
Cross Language Injection
.. am Beispiel von Kotlin..
entweder : Adapter mit Delegator
@CDINotMapped
publicclassDemoLogicKotlinWrapperimplementsDemoLogic{
private@InjectDemoLogicKotlinkotlin;
publicStringworkOnString(){
returnkotlin.workOnString();
}
}
JAVA
112. @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
114. @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
115. @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
116. @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
117. @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.
118. @SvenRuppert 120/122
finally at amazon..
my book with Dr, Heinz Kabutz
Book about Reflection - part one
Dynamic Proxies z.B. ...dynamic static proxies... ;-)