CDI: Nutzung von Referenzen

Dieses Thema CDI: Nutzung von Referenzen im Forum "Application Tier" wurde erstellt von miketech, 10. Aug. 2012.

Thema: CDI: Nutzung von Referenzen Hallo zusammen, ich habe folgendes Szenario: Ich habe eine Bean (Session Scoped) A. Diese Bean A erstellt...

  1. Hallo zusammen,

    ich habe folgendes Szenario:

    Ich habe eine Bean (Session Scoped) A. Diese Bean A erstellt eine Instanz einer Klasse, die das Interface B implementiert, mittels einer Factory.


    Code (Text):

    @Named
    @RequestScoped
    public class A() {


      public void doSomething() {
         B b = MyFactory.createB();
         b.doSomthingElse();
      }

    }

     
    Nun habe ich das Problem, dass ich von B heraus eigentlich eine Methode aus A aufrufen müsste. Wie gehe ich nun vor? Soll ich die aktuelle Instanz von A als Parameter übergeben? Oder ist das hässlich, wenn ich eigentlich mit CDI arbeite?

    Code (Text):


    @Named
    @RequestScoped
    public class A() {


      public void doSomething() {
         B b = MyFactory.createB(this);
         b.doSomthingElse();
      }

    }

     
    Allerdings erstellt MyFactory ja nur eine Instanz einer Klasse, die B implementiert und von diesen Klassen habe ich ca. 15 verschiedene. Ist es hier dann üblich, dennoch mit bspw. RequestScoped Beans für jede dieser 15 verschiedenen zu arbeiten? Wäre ja durchaus möglich, dass ich dann jeweils eine Instanz mittels CDI zurückliefere.

    Was ist denn hier BestPractice?

    Danke

    Mike
     
  2. Vielleicht helfen dir diese Java-Grundlagen weiter --> *Klick*
  3. Mal andersrum gefragt, wieso injizierst Du A und B nicht?
     
  4. Hi,

    danke für deine Antwort. Mit A mache ich das ja. Aber bei B gibt es zig verschiedene Varianten, wo ich abhängig von verschiedenen Parametern eine andere Variante benötige. Es wäre schon möglich in der Factory zu sagen:

    Code (Text):

    public class MyFactory {
      public static B create() {
        if ....
         return @Inject B1;
        else
         return @Inject B2;
      }
    }

    public class B {
      private @Inject A a;
    }
     
    Weiß nicht, ob das syntaktisch so möglich ist bei dem return. Aber ich habe so etwas meine Bedenken, dass ich den RequestScope nicht immer einhalte. Vielleicht benötige ich zwei verschiedene B1 in einem Request. Ich weiß nicht, ob ich dann nicht aus Versehen auf derselben Instanz arbeite, obwohl ich eigentlich zwei verschiedene bräuchte.

    Gruß

    Mike
     
  5. Zunächst würde ich grundlegend nochmal über die Architektur nachdenken. Statische Factories sind wahnsinnig schlecht mit Blick auf Testbarkeit da sowas quasi nicht weg zu mocken ist.

    Ohne Garantie auf Richtigkeit weil ich selbst kein CDI Pro bin würde ich aber folgendes versuchen. Ich würde mir für alle deine Implementierungen von B entsprechende Qualifier erstellen und dann direkt aus Klasse A die entsprechende Implementierung über Instance injizieren
    Code (Text):


     @Inject @Bimpl1
        private Instance<B> Bimpl1;

        @Inject @Bimpl2
        private Instance<B> Bimpl2;

        @Inject @Bdefault
        private Instance<B> Bdefault;
           
        private B b;

        protected void AMethode() {
            if (Bdefault = true) {
                b = Bdefault.get();
            } else if (!Bimpl1 = true) {
                b = Bimpl1.get();
               ........
            }
     
    Wobei auch Field Injection eigentlich nicht so günstig ist. Ich tendiere immer dazu alles im Konstruktor oder an der Methode wo ich es nutze zu injizieren.

    Um nun von B auf A zugreifen zu können und keine zirkuläre Abhängigkeit zu bekommen würde ich dann entsprechend in B eine lazy Injection machen:

    Code (Text):
    @Inject
        Instance<A> aInstance;

        public A getA()
        {
            return aInstance.get();
        }      
     
  6. Ich würde mich auch mal fragen, warum B eine Methode von A aufrufen muss, also was dieses Konstrukt realisieren soll. Evtl. gibt es da eine bessere Lösung.
     
  7. Wenn es wirklich so schwierig ist, das aktuell "richtige" B herauszufinden, brauchst du einen entsprechenden Dienst dafür, und den kannst du dir dann injizieren lassen.
     
  8. Hallo zusammen,

    danke für Eure Antworten. Ich werde dann tatsächlich noch einmal umdenken. Das ist dann irgendwie noch nicht ideal von der Architektur. Ich werde versuchen, wirklich komplett auf CDI Beans zu setzen, weil dann muss ich diese Referenzen nicht mitschleifen. Das ist nur, weil ich sonst von einer normalen (nicht CDI) Bean nicht mehr auf die CDI Bean zugreifen kann.

    Gruß

    Mike
     
  9. KOSTENLOSES Java-Grundlagen Training im Wert von 39 € Sichere dir hier den kostenlosen Zugriff auf umfangreiches Java-Know How und starte richtig durch!