2010-08-18 13 views
6

[UPDATE : Dopo la discussione sul forum Glassfish/ML a http://forums.java.net/jive/thread.jspa?messageID=480532 un bug è stata depositata contro Glassfish https://glassfish.dev.java.net/issues/show_bug.cgi?id=13040 per questo problema.]"Impossibile convertire ejbRef per EJB" sul CDI (Weld) iniezione di @Stateless EJB in @SessionScoped JSF2 fagiolo in Glassfish

Sto provando a iniettare una vista no-interface locale di un bean EStat @ in un bean di supporto JSF2 @Named @ javax.enterprise.context.SessionScoped. L'EJB è uno dei tanti che estendono una classe base generica astratta. L'inserimento di "@Inject TheEJBClass varName" non riesce con "Impossibile convertire ejbRef per ejb TheEJBClass in un oggetto business di tipo classe my.package.name.TheAbstractBase". [modifica: In realtà, l'iniezione ha esito positivo, ma la risoluzione del metodo nel proxy iniettato per i metodi ereditati dalle superclassi fallisce.] Se uso "@EJB TheEJBClass varName", varName rimane nullo, ovvero non viene iniettato nulla.

Dettagli:

Io corro Glassfish 3.0.1 su Linux (Ubuntu 10.04 nel caso in cui è importante) e avendo reali problemi di gestione iniezione dei miei EJB modello dati nella mia sessione JSF2 ambito modelli utilizzando CDI (saldatura) . E sì, prima che tu me lo chieda, ho bean.xml sul posto e CDI si sta attivando per eseguire l'iniezione.

Se inietto con un'annotazione @EJB, ad esempio:

@EJB TheEJBClass memberName; 

... il bean non è effettivamente iniettata, lasciando memberName nullo.

Se faccio l'iniezione con un'annotazione CDI @Inject:

@Inject TheEJBClass memberName; 

... poi CDI si lamenta quando chiamo un metodo di "memberName" che è implementata in una superclasse di TheEJBClass e non sottoposto a override in TheEJBClass sua auto, riportando:

java.lang.IllegalStateException: Unable to convert ejbRef for ejb TheEJBClass to a business object of type class my.package.name.TheAbstractBase 
    at 
com.sun.ejb.containers.EjbContainerServicesImpl.getBusinessObject(EjbContainerServicesImpl.java:104) 
at 
org.glassfish.weld.ejb.SessionObjectReferenceImpl.getBusinessObject(SessionObjectReferenceImpl.java:60) 
.... 

ho provato a convertire la base per classe concreta e de-generifying, ma lo stesso problema, quindi non credo che mi colpisce gli insetti di saldatura con basi generiche (https://jira.jboss.org/browse/WELD-305, https://jira.jboss.org/browse/WELD-381, https://jira.jboss.org/browse/WELD-518).

Un profilo del codice, con la qualificazione pacchetto completo sulle annotazioni aggiunte per chiarezza, è:

// JSF2 managed backing bean. 
// 
// Called via #{someJSF2Model.value} in a JSF2 page 
// 
@javax.inject.Named 
@javax.enterprise.context.SessionScoped 
public class SomeJSF2Model implements Serializable { 
    @javax.inject.Inject TheEJBClass member; 

    public Integer getValue() { 
     return member.getValue(); 
    } 
    // blah blah 
} 

// One of several EJB classes that extend TheAbstractBase 
@javax.ejb.Stateless 
public class TheEJBClass extends TheAbstractBase { 
    // blah blah 
    // does **NOT** override "getValue()" 
} 

public abstract class TheAbstractBase { 
    // blah blah 
    public Integer getValue() { 
     return 1; 
    } 
} 

Nota che l'iniezione fa lavoro se sovrascrivo TheAbstractBase.getValue() in TheEJBClass, o se io chiamare un metodo definito in TheEJBClass e non una superclasse. Sembra che il problema sia qualcosa a che fare con l'ereditarietà.

Il codice molto simile che utilizzava le funzioni di ciclo di vita e di iniezione incorporate di JSF2 ha funzionato, ma dato che questo è un nuovo progetto e il CDI è dove si stanno dirigendo le cose in futuro, ho pensato che fosse meglio provare per CDI. Ecco quello che ho iniziato con l'utilizzo di iniezione JSF2/EJB, che ha funzionato:

// JSF2 managed backing bean. Using @ManagedBean and JSF2's @SessionScoped 
// instead of CDI @Named and CDI @SessionScoped this time. 
// 
@javax.faces.bean.ManagedBean 
@javax.faces.bean.SessionScoped 
public class SomeJSF2Model implements Serializable { 
    @javax.ejb.EJB TheEJBClass member; 
    public Integer getValue() { 
     return member.getValue(); 
    } 
    // blah blah 
} 

// One of several EJB classes that extend TheAbstractBase 
// Unchanged from CDI version 
@javax.ejb.Stateless 
public class TheEJBClass extends TheAbstractBase { 
    // blah blah 
    // does **NOT** override "getValue()" 
} 

// Unchanged from CDI version 
public abstract class TheAbstractBase { 
    // blah blah 
    public Integer getValue() { 
     return 1; 
    } 
} 

Attualmente sto lavorando a mettere insieme un caso di test self-contained, ma ho pensato di sparare la questione ora nel caso in cui questo è qualcosa in cui sto solo facendo qualcosa di stupido o c'è una soluzione ben nota che il mio Google-fu non è in grado di trovare. Perché ha funzionato con l'iniezione JSF2/EJB, ma fallisce con l'iniezione CDI?

(Da ri-postato sui forum Glassfish come http://forums.java.net/jive/thread.jspa?threadID=152567)

+0

Ho creato un test case che dimostra questo problema. Sembra dipendere da come il wrapper JavaAssist generato da CDI risolva i riferimenti ai metodi definiti nelle superclassi. Il problema non è in realtà al momento dell'iniezione, ma al momento un metodo ereditato da una superclasse viene chiamato tramite il wrapper iniettato. L'uso della denominazione e dell'ambito JSF2 o CDI non ha nulla a che fare con esso, è solo @EJB vs @Inject Vedere commenti ed esempi in: http://www.postnewspapers.com.au/~craig/public_files_keep/ ErrorDemo.zip (src) e http://www.postnewspapers.com.au/~craig/public_files_keep/ErrorDemo.war (webapp). –

+0

... e per il dolore bonus, il problema è praticamente invertito in JBoss AS 6. L'iniezione CDI funziona bene, ma l'iniezione JSF2 fallisce. –

risposta

3

Come notato sopra, si tratta di una saldatura/GlassFish bug.

Correzione: rinunciare a Glassfish e passare a JBoss AS 7, che in realtà funziona la maggior parte del tempo.

+2

corretto nel 2010, https://java.net/jira/browse/GLASSFISH-13040 – ymajoros