[更新: Glassfish フォーラム/ML でhttp://forums.java.net/jive/thread.jspa?messageID=480532で議論した後、Glassfish https://glassfish.dev.java.net/issuesに対してバグが報告されました。この問題については/show_bug.cgi?id=13040を参照してください。]
@Stateless EJB のローカルの非インターフェース ビューを JSF2 @Named @javax.enterprise.context.SessionScoped バッキング Bean に注入しようとしています。EJB は、抽象ジェネリック基本クラスを拡張するいくつかのクラスの 1 つです。「@Inject TheEJBClass varName」の挿入は、「ejb TheEJBClass の ejbRef をタイプ クラス my.package.name.TheAbstractBase のビジネス オブジェクトに変換できません」で失敗します。[編集: 実際には、インジェクションは成功しますが、スーパークラスから継承されたメソッドのインジェクトされたプロキシでのメソッド解決は失敗します。]「@EJB TheEJBClass varName」を使用すると、varName は null のままです。つまり、何もインジェクトされません。
詳細:
Linux (重要な場合は Ubuntu 10.04) で Glassfish 3.0.1 を実行していますが、CDI (Weld) を使用してデータ モデル EJB を JSF2 セッション スコープ モデルに挿入する際に問題が発生しています。はい、あなたが尋ねる前に、beans.xml が配置されており、CDI がアクティブ化されてインジェクションが実行されています。
@EJB アノテーションを挿入すると、次のようになります。
@EJB TheEJBClass memberName;
... EJB は実際には注入されず、memberName は null のままです。
CDI @Inject アノテーションを使用して注入すると、次のようになります。
@Inject TheEJBClass memberName;
...次に、TheEJBClass のスーパークラスに実装され、TheEJBClass 自体でオーバーライドされていない「memberName」のメソッドを呼び出すと、CDI が不平を言い、次のように報告します。
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)
....
ベースを具象クラスに変換して非ジェネ化しようとしましたが、同じ問題が発生したため、一般的なベースで Weld バグにヒットしているとは思いません ( https://jira.jboss.org/browse /WELD-305、https://jira.jboss.org/browse/WELD-381、https://jira.jboss.org/browse/WELD-518 )。
わかりやすくするために注釈に完全なパッケージ修飾を追加したコードの概要は次のとおりです。
// 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;
}
}
TheEJBClass で TheAbstractBase.getValue() をオーバーライドするか、スーパークラスではなく TheEJBClass で定義されたメソッドを呼び出すと、インジェクションが機能することに注意してください。問題は継承に関係しているようです。
JSF2 のビルトイン ライフサイクルとインジェクション機能を使用する非常によく似たコードが機能しましたが、これが新しいプロジェクトであり、CDI が将来に向かっていることを考えると、CDI を試すのが最善だと思いました。JSF2/EJB インジェクションの使用から始めたものは次のとおりです。
// 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;
}
}
私は現在、自己完結型のテスト ケースの作成に取り組んでいますが、これが何かばかげたことをしているだけの場合や、Google-fu ではないよく知られている解決策がある場合に備えて、今すぐ質問を開始すると考えました。見つけるまでt。JSF2/EJB インジェクションでは機能するのに、CDI インジェクションでは失敗するのはなぜですか?
(Glassfish フォーラムにhttp://forums.java.net/jive/thread.jspa?threadID=152567として再投稿されたため)