Warum ich so auf das c von cdi stehe

153 Aufrufe

Veröffentlicht am

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.

Veröffentlicht in: Software
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
153
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
5
Aktionen
Geteilt
0
Downloads
0
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Warum ich so auf das c von cdi stehe

  1. 1. Warum CDI oder gibt es einen tieferen Sinn dahinter? warum denn CDI ? ;-)
  2. 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. 3. @SvenRuppert 5/122 Warum CDI oder gibt es einen tieferen Sinn dahinter? lösen/entfernen von statischen Abhängigkeiten
  4. 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. 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. 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. 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. 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. 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. 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. 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. 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
  13. 13. @SvenRuppert 15/122 Warum CDI oder gibt es einen tieferen Sinn dahinter? Haben wir damit etwas erreicht?
  14. 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. 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. 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. 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. 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. 19. @SvenRuppert 21/122 Warum CDI oder gibt es einen tieferen Sinn dahinter? Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert.
  20. 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. 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. 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. 23. @SvenRuppert 25/122 Warum CDI oder gibt es einen tieferen Sinn dahinter? Anforderung Nr 1: keine statischen Abhängigkeiten zu spezifischen Implementierungen
  24. 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. 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 ???
  26. 26. @SvenRuppert 28/122 Lösungsversuch Nr 1 basierend auf Java SE Eine etwas dynamischere Lösung...
  27. 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. 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. 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. 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. 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. 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. 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. 34. @SvenRuppert 36/122 endlich CDI ;-) basierend auf Weld / WELD-SE Instanzen werden per @Inject durch den Container zur Verfügung gestellt
  35. 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. 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. 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. 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. 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. 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. 41. @SvenRuppert 43/122 endlich CDI ;-) basierend auf Weld / WELD-SE Instanzen können auch erst zum Zeitpunkt der Verwendung instanziiert werden.
  42. 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. 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. 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. 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. 46. @SvenRuppert 48/122 CDI was wurde bis jetzt erreicht? Trennung der statischen Abhängigkeiten auf Klassenebene innerhalb der Vererbung
  47. 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. 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. 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. 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. 51. @SvenRuppert 53/122 CDI was wurde dafür in Kauf genommen? statische Kopplung über AnnotationsLiterale: @Inject@MyQualifierListliste; JAVA
  52. 52. @SvenRuppert 54/122 CDI was wurde dafür in Kauf genommen? statische Kopplung über AnnotationsLiterale: schlechterer Umgang mit Generics @Inject@MyQualifierListliste; JAVA
  53. 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. 54. @SvenRuppert 56/122 CDI explained by code HelloLogger zum aufwärmen/wiederholen klassischer Fall, Logger im System @Inject@CDILoggerLoggerlogger; JAVA
  55. 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. 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. 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. 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. 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. 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
  61. 61. @SvenRuppert 63/122 CDI explained by code Qualifier und AnnotationsLiterale @Inject@CDILoggerLoggerlogger; JAVA
  62. 62. @SvenRuppert 64/122 CDI explained by code Qualifier und AnnotationsLiterale @Inject@CDILoggerLoggerlogger; JAVA @Producer@CDILoggerLoggercreate(...); JAVA
  63. 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. 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. 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. 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. 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. 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. 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
  70. 70. @SvenRuppert 72/122 CDI explained by code 1 / 6 ContextResolver / aus der Sicht des Entwicklers
  71. 71. @SvenRuppert 73/122 CDI explained by code 1 / 6 ContextResolver / aus der Sicht des Entwicklers
  72. 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. 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
  74. 74. @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
  75. 75. @SvenRuppert 77/122 CDI explained by code 3b / 6 ContextResolver Durch Interzeptoren meist nur allgemeine Umschaltlogik darstellbar
  76. 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. 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. 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
  79. 79. @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
  80. 80. @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
  81. 81. @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
  82. 82. @SvenRuppert 84/122 CDI explained by code 6 / 6 ContextResolver Wir sind nun in der Lage dynamisch auf den Systemzustand zu reagieren.
  83. 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. 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
  85. 85. @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
  86. 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. 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. 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. 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. 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. 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. 92. @SvenRuppert 94/122 CDI explained by code 4a / 7 CDI managed DynamicObjectAdapter - besserer Decorator Injizieren der Referenz auf DemoLogic
  93. 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. 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. 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. 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. 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. 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. 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. 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.
  101. 101. @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
  102. 102. @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
  103. 103. @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
  104. 104. @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
  105. 105. @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
  106. 106. @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
  107. 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. 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. 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. 110. @SvenRuppert 112/122 Cross Language Injection .. am Beispiel von Kotlin.. classDemoLogicKotlin(){ publicfunworkOnString():String{ return"DemoLogicKotlin" } } JAVA
  111. 111. @SvenRuppert 113/122 Cross Language Injection .. am Beispiel von Kotlin.. entweder : Adapter mit Delegator @CDINotMapped publicclassDemoLogicKotlinWrapperimplementsDemoLogic{ private@InjectDemoLogicKotlinkotlin; publicStringworkOnString(){ returnkotlin.workOnString(); } } JAVA
  112. 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
  113. 113. @SvenRuppert 115/122 CDI und TDD ... kaskadierte MOCKS Service A injected Service B injected Service C
  114. 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. 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. 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. 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. 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... ;-)
  119. 119. <Thank You!> g+ www.google.com/+SvenRuppert twitter @SvenRuppert www www.rapidpm.org
  120. 120. www www.rapidpm.org github github.com/svenruppert

×