2010-08-18 11 views
6

[UPDATE Po dyskusji na przeźroczkom forach/ml w http://forums.java.net/jive/thread.jspa?messageID=480532 błąd został złożony na GlassFish https://glassfish.dev.java.net/issues/show_bug.cgi?id=13040 w tym wydaniu.]„Nie można przekształcić ejbRef do EJB” na CDI (spoiny) wstrzyknięcie @Stateless EJB w @SessionScoped JSF2 bean GlassFish

Próbuję wprowadzić lokalny widok bez interfejsu użytkownika @Stateless EJB do komponentu bean JSF2 @Named @ javax.enterprise.context.SessionScoped. EJB jest jednym z kilku, które rozszerzają abstrakcyjną ogólną klasę bazową. Injection "@Inject TheEJBClass varName" kończy się niepowodzeniem z "Nie można dokonać konwersji ejbRef dla ejb TheEJBClass na obiekt biznesowy klasy type my.package.name.TheAbstractBase". [edytuj: W rzeczywistości okazuje się, że wstrzyknięcie się powiedzie, ale nie udało się rozwiązać problemu w zastrzyku proxy dla metod odziedziczonych po nadklasach.] Jeśli użyję "@EJB TheEJBClass varName", to varName pozostanie puste, tzn. Nic nie zostanie wstrzyknięte.

Szczegóły:

biegnę GlassFish 3.0.1 na Linux (Ubuntu 10.04 w przypadku jest to ważne) i mający rzeczywiste problemy z obsługą zastrzyk moim modelu danych EJB w moim sesji JSF2 scoped modele wykorzystaniem CDI (spoiny) . I tak, zanim zapytasz, mam plik bean.xml w miejscu, a CDI aktywuje się, aby wykonać iniekcję.

Gdybym wstrzyknąć go z adnotacją @EJB, np:

@EJB TheEJBClass memberName; 

... EJB w rzeczywistości nie jest wstrzykiwany, pozostawiając membername null.

Gdybym wstrzyknąć go z CDI @Inject adnotacji:

@Inject TheEJBClass memberName; 

... potem CDI narzeka gdy zgłoszę metodę „membername”, który jest realizowany w nadklasą TheEJBClass i nie przeciążonych w TheEJBClass jego jaźń, raportowanie:

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) 
.... 

próbowałem konwersji bazy do konkretnej klasy i dE-generifying, ale występuje ten sam problem, więc nie sądzę, jestem uderzając błędów spoiny z zasadami ogólnymi (https://jira.jboss.org/browse/WELD-305, https://jira.jboss.org/browse/WELD-381, https://jira.jboss.org/browse/WELD-518).

Zarys kodu, z pełnym pakietem kwalifikacji na adnotacji dodanych dla jasności, to:

// 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; 
    } 
} 

Należy zauważyć, że wtrysk robi pracę gdybym przesłonić TheAbstractBase.getValue() w TheEJBClass, lub jeśli wywołaj metodę zdefiniowaną w TheEJBClass, a nie jakiejkolwiek nadklasie. Wygląda na to, że problem ma coś wspólnego z dziedziczeniem.

Bardzo podobny kod, który wykorzystywał wbudowane funkcje JSF2 w zakresie cyklu życia i wtrysku, ale biorąc pod uwagę, że jest to nowy projekt, a CDI jest miejscem, w którym sprawy zmierzają w przyszłości, uznałem, że najlepiej jest wybrać CDI. Oto co zaczęło się z wykorzystaniem iniekcji JSF2/EJB, który pracował:

// 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; 
    } 
} 

Obecnie pracuję na łącząc samodzielne przypadek testowy, ale pomyślałem, że wystrzelić pytanie teraz w przypadku tego jest czymś, co robię po prostu głupio lub jest dobrze znane rozwiązanie, którego mój Google-fu nie jest w stanie znaleźć. Dlaczego działa z wtryskiem JSF2/EJB, ale kończy się niepowodzeniem z iniekcją CDI?

(Ponieważ ponowne pisał na forach GlassFish jako http://forums.java.net/jive/thread.jspa?threadID=152567)

+0

Zbudowałem walizkę testową, która demonstruje ten problem. Wydaje się, że sprowadza się to do tego, w jaki sposób wygenerowany przez CDI wrapper JavaAssist rozwiązuje odwołania do metod zdefiniowanych w nadklasach. Problem nie dotyczy czasu iniekcji, ale w tym czasie metoda odziedziczona z nadklasy jest wywoływana przez wstrzyknięte opakowanie. Używanie nazw i zakresu JSF2 lub CDI nie ma z tym nic wspólnego, to tylko @EJB kontra @Inject Zobacz komentarze i przykład w: http://www.postnewspapers.com.au/~craig/public_files_keep/ ErrorDemo.zip (src) i http://www.postnewspapers.com.au/~craig/public_files_keep/ErrorDemo.war (webapp). –

+0

... i dla dodatkowego bólu, problem jest prawie odwrócony w JBoss AS 6. Wtryskiwanie CDI działa dobrze, ale wtrysk JSF2 nie działa. –

Odpowiedz

3

Jak wspomniano powyżej, to jest Weld/GlassFish bug.

Napraw: Oddaj się na Glassfish i przejdź do JBoss AS 7, który działa przez większość czasu.

+2

poprawiona w 2010 r., Https://java.net/jira/browse/GLASSFISH-13040 – ymajoros