2016-03-21 5 views
0

Ich habe folgendes Setup:Kann eine CDI-Bean-Methode eine von ihr erstellte verwaltete Bean zurückgeben?

@Applicationscoped 
@Transactional(txtype.Requires_new) 
Public class querybean { 

    @Inject ExternalSysrltem externalSystemProxy; 

    Public Handle gethandleByKey(String key) { 
     return new Handle(/*do external Systems Query, returns an ExternalHandle Object*/) 
    } 

    Public static class Handle { 
     ExternalHandle eh; 
     /*protected so that User of class cannot Instantiate it otherwise that by getHandleByKey()*/ 
     Protected Handle(ExternalHandle arg) { 
      This.eh = arg; 
     } 

     Public String getHandleInfo() { 
      Return This.eh.getName() + "/" + this.eh.getState()..; 
      /*generally wrap the ExternallHandle with businesslogic to hide direct access to the complex ExternalService's Interface*/ 
     } 
    } 
} 

Kann ich Handle bekommen eine Managed Bean zu sein, die mit @Transactional mit Anmerkungen versehen werden kann und es immer noch in der getHandleByKey Methode zur Laufzeit erstellen, indem Sie das externe System abfragen?

+0

Sie nutzen könnten [ '@ Produces'] (http://stackoverflow.com/questions/16534728/please-explain-the-produces-annotation-in-cdi). – Geinmachi

Antwort

1

Eine statische innere Klasse kann eine Bohne nach der spec sein. In Ihrem Beispiel ist es aufgrund seines Konstruktors keine Bean. Wie gesagt in den Kommentaren können Sie einen Hersteller verwenden, aber eine erzeugte Bean kann nicht (mit @Transaction hier)

Wenn Sie Ihr Muster behalten möchten abgefangen werden, werden Sie eine sehr komplexe Erweiterung zu schaffen haben, da es sein sollte arbeite auf niedriger Stufe, um sicherzustellen, dass der Abfangjäger aktiviert wird.

Ich schlage vor, dass Sie sich für etwas gehen einfacher, indem Sie Ihre ExternalHandle Auflösung in Handle Bean abzuschieben, so dass Sie eine String verwenden, um es zu konstruieren.

Erstellen Sie zunächst ein Qualifikationsmerkmal mit einem nicht bindenden Mitglied, um Informationen an Ihren Konstruktor zu senden.

@Target({TYPE, METHOD, PARAMETER, FIELD}) 
@Retention(RUNTIME) 
@Documented 
@Qualifier 
public @interface Keyed { 

    @Nonbinding 
    String key(); 
} 

Erstellen Sie dann eine wörtliche für Ihre Anmerkung mit einem bestimmten key Wertschöpfung einer Anmerkung Instanz zu ermöglichen.

public class KeyedLiteral extends AnnotationLiteral<Keyed> implements Keyed { 

    private final String key; 

    public KeyedLiteral(String key) { 
     this.key = key; 
    } 

    @Override 
    public String key() { 
     return key; 
    } 
} 

Mit programmatic Lookup und InjectionPoint Ihren Schlüsselwert zu übertragen. Ihr Code wird sein wie:

@Applicationscoped 
@Transactional(txtype.Requires_new) 
Public class querybean { 
    @Inject 
    @Any 
    Instance<Handle> handles; 

    Public Handle gethandleByKey(String key) { 
     return instances.select(new KeyedLiteral(key)).get() 
    } 

    @Dependent 
    @Transactional 
    @Keyed("") //enforce the presence of the annotation for the constructor 
    Public static class Handle { 

     ExternalHandle eh; 

     // needed to make the bean proxyable (mandatory for the interceptor bound)) 
     Protected Handle() {} 

     @Inject 
     Protected Handle(InjectionPoint ip, ExternalSysrltem externalSystem) { 
      String key=ip.getAnnotated().getAnnotation(Keyed.class).key(); 
      eh = /*do external Systems Query, returns an ExternalHandle Object from key and externalSystem*/ 
     } 

     Public String getHandleInfo() { 
      Return This.eh.getName() + "/" + this.eh.getState()..; 
      /*generally wrap the ExternallHandle with businesslogic to hide direct access to the complex ExternalService's Interface*/ 
     } 
    } 
}