7

いくつかの理由で、アプリケーションを 2 つの別個のアーティファクト ( Users-ejb.jarおよびUsers-war.war )としてデプロイしたいと考えています。これらは同じearにパッケージ化されていません(ただし、同じJBoss AS 7.1 インスタンスにデプロイされています)。Users-war.warには、Users-ejb.jarにパッケージ化された EJB3 を注入したいバッキング Bean (JSF マネージド Bean として注釈が付けられています) があります。すべてが 1 つのearにパッケージ化されていたときに機能していた単純な@EJBインジェクションは、 Users-ejb.jarUsers-war.warが別々にデプロイされると機能しなくなります。

私のセットアップの絞り込まれた単純化された例は次のとおりです。

EJB3 ビーン

import javax.ejb.*;

(...)

@Stateless(name="userFacade")
@Local(IUserFacadeLocal.class)
@Remote(IUserFacadeRemote.class)
public class UserFacade extends AbstractFacade<User> implements IUserFacadeLocal, IUserFacadeRemote {

バッキングビーン

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.ejb.EJB;

import entities.User;
import facades.IUserFacadeRemote;
import facades.IUserFacadeLocal;

@ManagedBean(name="indexBackingBean")
@SessionScoped
public class IndexBackingBean implements Serializable {

    @EJB(beanName="userFacade")
    private IUserFacadeLocal userFacade;

バッキング Bean で EJB3 Bean のタイプを IUserFacadeRemote (IUserFacadeLocal ではなく) として宣言するなど、さまざまな組み合わせを試しましたが、Users-war.warモジュールがデプロイされている場合、それらはすべて同じ例外で失敗します。

Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException:
JBAS014543: No EJB found with interface of type 'facades.IUserFacadeLocal' and
 name 'userFacade' for binding controllers.IndexBackingBean/userFacade

Users-ejb.jarは問題なく JBoss AS 7.1 にデプロイされますが、Users -war.warがデプロイされると、JBoss は、注入するはずの Bean が見つからないと文句を言います。

ただし、次を使用して、JNDI を使用して EJB3 Bean への参照を取得できます。

String jndiName = "java:global/Users-ejb/userFacade!facades.IUserFacadeRemote";
this.userFacade = (IUserFacadeRemote) new InitialContext().lookup(jndiName);

それにもかかわらず、@EJB インジェクションは機能していないようです。

更新: Tom Andersonに よる以下の提案に従いましたが、機能するインジェクションは次のとおりです。

@EJB(mappedName = "java:global/Users-ejb/userFacade!facades.IUserFacadeRemote")

私が理解していれば、ベンダー固有のmappedName属性を正しく使用しています。ベンダーに依存しない方法でインジェクションを機能させることができませんでした。

4

3 に答える 3

4

EE仕様のこの領域を十分に理解して、決定的な回答を提供できればと思いますが、そうではありません。

JBoss EJBのドキュメントには、次のように書かれています。

  • @EJB アノテーションには、mappedName() 属性もあります。仕様では、これはベンダー固有のメタデータのままですが、JBoss は、参照している EJB のグローバル JNDI 名として MappedName() を認識します。mappingName() を指定した場合、他のすべての属性は無視され、このグローバル JNDI 名がバインドに使用されます。
  • 属性が定義されていない @EJB を指定した場合 [...] 次に、次の規則が適用されます。
    • 参照元 Bean の EJB jar は、@EJB インジェクションで使用されるインターフェースを持つ EJB を検索します。同じビジネス インターフェースを発行する EJB が複数ある場合は、例外がスローされます。そのインターフェースを持つ Bean が 1 つしかない場合は、その Bean が使用されます。
    • そのインターフェースをパブリッシュする EJB を EAR で検索します。重複がある場合は、例外がスローされます。それ以外の場合は、一致する Bean が返されます。
    • そのインターフェースの EJB を JBoss でグローバルに検索します。繰り返しますが、重複する場合は例外がスローされます。
  • @EJB.beanName() は に対応します。beanName() が定義されている場合は、beanName() を検索のキーとして使用する以外は、属性を定義せずに @EJB と同じアルゴリズムを使用します。この規則の例外は、ejb-link '#' 構文を使用する場合です。「#」構文を使用すると、参照している EJB が存在する EAR 内の jar への相対パスを指定できます。詳細については、仕様を参照してください

「そのインターフェースの EJB を JBoss でグローバルに検索する」は、あなたが書いたようなインジェクションが機能することを確かに示唆しています。確かに、それがなくても動作するはずbeanNameです。ただし、WAR 内のコンポーネントの観点から見ると、EJB-JAR 内のコンポーネントはリモートであるため、リモート インターフェースを使用する必要があるのではないかと思います。

だから、私が最初に試すことは次のとおりです。

@EJB
private IUserFacadeRemote userFacade;

問題が発生した場合に備えて、なしでbeanName。しかし、あなたはそれを試したようです。

インジェクションへの通常のアプローチが機能しない場合、mappedNameJBoss ではグローバル JNDI 名である を介してインジェクションを試みることにフォールバックする可能性があります。そう:

@EJB(mappedName = "java:global/Users-ejb/userFacade!facades.IUserFacadeRemote")
private IUserFacadeRemote userFacade;

これは明らかにかなり醜いです。

とにかく、頑張ってください!

EDIT : 他に試すことができるのはbeanName、EJB-JAR を明示的に指定する修飾された相対を使用することです。

@EJB(beanName = "Users-ejb.jar#userFacade")
private IUserFacadeRemote userFacade;

WAR と EJB-JAR は EAR にパッケージ化されていないため、次のようにする必要がある場合があります。

@EJB(beanName = "../Users-ejb.jar#userFacade")
private IUserFacadeRemote userFacade;

しかし、この時点では、私はただ推測しています。

EDIT STRIKES BACK : 非常に単純なことを見落としている可能性があります。アノテーションのlookup属性を@EJB使用すると、「対象の EJB コンポーネントの JNDI 名を含むポータブル ルックアップ文字列」を指定できます。したがって、次のようになります。

@EJB(lookup = "java:global/Users-ejb/userFacade!facades.IUserFacadeRemote")
private IUserFacadeRemote userFacade;

うまくいくかもしれません。これは基本的に、JBoss 固有の の使用のポータブル バージョンですmappedName

于 2012-08-13T13:32:32.163 に答える
0

@TomAndersonが言ったように、クロスアーティファクトルックアップを実現する標準的な方法は、注釈のlookup属性です。@EJB

これがどのように機能するかを説明する完全な Maven プロジェクトを次に示します:
https://github.com/mrts/remote-ejb-injection

nameEJB クラスの属性を使用する必要はありません。ルックアップでクラス名を指定するだけで十分です。上記の例からの引用:

// in API JAR
@Remote
public interface HelloService { ... }

// in EJB JAR
@Stateless
public class HelloServiceImpl implements HelloService { ... }

// in WAR
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    @EJB(lookup = "java:global/service-ear/service-ejb-impl/HelloServiceImpl!" +
                  "ee.mrts.service.HelloService")
    private HelloService helloService;

    ...
}

(つまり、Just Works™HelloServiceImplで直接使用します。)lookup

于 2016-07-08T15:49:46.503 に答える
0

私は Wildfly でこのシナリオをテストしており、ejb を指す war 内に jboss-deployment-structure.xml がある場合、上記のようにローカル インターフェイスで動作することがわかりました。それ以外の場合、JBoss および Wildfly でのモジュラー クラスのロードにより、上記の war が ejbs クラスについて実際に「認識」できないため、ClassNotFoundException がスローされます。ファイルの内容は次のとおりです。

<jboss-deployment-structure>
    <deployment>
        <dependencies>
            <module name="deployment.Users-ejb.jar" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

そして、JSF Bean は以下を使用できます。

@EJB(lookup = "java:global/Users-ejb/userFacade!facades.IUserFacadeRemote")
private IUserFacadeLocal userFacade;
于 2014-10-24T20:29:30.700 に答える