4

ステートレスBean内のステートフルセッションBeanにアクセスすることは可能ですか?

私の問題は、UserというセッションBeanがあり、ステートレスBean内のユーザー情報にアクセスしたいということです...

私はこのようにしようとしています:

Ejb側:

@Stateless
public class OfferManagerBean implements OfferManagerLocal, OfferManager
{
    @Resource 
    private SessionContext context;
    @EJB
    private ro.project.ejb.interfaces.User user;
    public String getUsername()
    {
        user = (ro.project.ejb.interfaces.User) context.lookup("java:global/project/projectEJB/User!ro.project.ejb.interfaces.User");
        return user.getUsername();
}

クライアント側

 User user = (User) ctx.lookup("java:global/project/projectEJB/User!ro.project.ejb.interfaces.User");
 user.setUsername("Alex");

 OfferManager offerManager = (OfferManager) ctx.lookup("java:global/project/projectEJB/OfferManagerBean!ro.project.ejb.interfaces.OfferManager");
 assertEquals(offerManager.getUsername(), "Alex");

このテストケースの結果は次のとおりです。java.lang.AssertionError: expected:<null> but was:<Alex>

失敗します。ステートフルBeanを要求している方法で、新しいインスタンスが返されているようです。

  1. なぜこれが機能しないのか知っています。私のテストが失敗したので:P。新しいインスタンスを取得します。
  2. クライアント側でミスをする可能性があるため、クライアント側でカウントしたくないため、EJBにログインしているユーザーの特定のアクセス許可を確認したい。または、他の開発者にプロジェクトのGUIを作成するように指示します。
  3. RCPアプリケーションにログインする方法がわからないため、JavaEEセキュリティを使用したくない
  4. 私の主な質問は次のとおりです。EJB内のセッションBean(クライアントが所有しているものと同じ)にアクセスするにはどうすればよいですか。そしてどうやって?

私はこの男が尋ねているのとほぼ同じことを求めています:rmiejb呼び出しでの再利用可能なログインセッションの概念

私はそれをやりたいのですが、JAASではやりません...

前もって感謝します

4

4 に答える 4

10

Bean(SLSB)にBean(SFSB)を注入しないでください。SFSBは、クライアントが存続する限り存続します(クライアントは、SFSBが注入されたインスタンスであり、この場合はSLSB自体です)。ただし、SLSBはステートレスであることが意図されており、ほとんどのコンテナーはそれらをプールに持っています。したがって、SLSBは使用後にプールに戻るたびに、他の場所で完全に再利用されますが、SLSBが初めて作成されたときと同じSFSBインスタンスを保持します。これは、望ましくない結果につながる可能性があります。@Stateful@Stateless

また、JNDIからSFSBを取得するたびに、他の場所で共有されていないSLSBとは異なり、まったく新しいインスタンスを取得します。その場合、SFSBのクライアントは、JNDIからSFSBを取得した現在のクライアントクラスインスタンスになります。このインスタンスを自分で保持し、トランザクションの実行が完了するまで、まったく同じインスタンスを再利用する必要があります。方法の1つは、自分でHTTPセッションに保存するか、使用しているMVCフレームワークのセッションスコープのマネージドBeanに保存することです。

機能要件は私には完全に明確ではないので、特定の問題を解決する方法を適切に答えるのは難しいですが、実際にはユーザーをSFSBではなくHTTPセッションに格納する必要があるという印象があります。セッションBeanに関する最も一般的な初心者の間違いは、EJBコンテキストの「セッション」をHTTPセッションであると誤って解釈することです。

より詳細な説明については、同じ種類の質問に関するこの関連する回答も参照してください。JSFリクエストスコープBeanは、リクエストごとに新しいステートフルセッションBeanを再作成し続けますか?あなたの質問履歴によると、あなたはJSFに精通しているので、この答えは簡単に理解できるはずです。

于 2012-02-21T20:29:38.143 に答える
3

一般に、ステートレスBean内の特定の既存のステートフルセッションBeanにアクセスすることができます。たとえば、ステートレスセッションBeanのビジネスメソッドへの引数として指定できます。

しかし、あなたがしようとしていることはうまくいきません。理由は、依存インジェクション(@EJB)とルックアップ(ctx.lookup ...)の両方がnewInstanceを呼び出すことが保証されており、その結果、新しいインスタンスが作成されるためです。

これは、仕様書で次の言葉で説明されています。

セッションBeanインスタンスの存続期間は、クライアントが依存性注入またはJNDIルックアップを介してステートフルセッションBeanインスタンスへの参照を取得したとき、またはクライアントがセッションBeanのホームインターフェイスでcreateメソッドを呼び出したときに始まります。これにより、コンテナはセッションBeanクラスでnewInstanceを呼び出して、新しいセッションBeanインスタンスを作成します。

于 2012-02-21T20:29:58.283 に答える
2

他の人がまだ十分に明確になっていない場合:あなたはそれを間違っています!;)

混乱を招く可能性があることに同意しますが、EJBセッションBeanの唯一のセッションは、InititalContextから取得したプロキシBeanに保持されます。

このコンテキストから取得するさまざまなBeanは、いかなる種類の共通セッションも共有しません。EJBでは、BeanはEJBセッションに格納されませんが、このセッションです。

つまり、InitialContext(コード内のctx)は、HttpSessionのEJBと同等ではありません。

さらに悪いことに、コード内でユーザーがEJBBeanである可能性があります。これは間違っています。

ユーザーは、アプリケーションの名詞です。これらは、JPAエンティティまたは単純な「通常の」JavaBeanによって表されます。EJBは、アプリケーションに動詞を実装するためのものです:サービス、DAO、リポジトリなど。

ステートフルセッションBeanの状態は、ビジネスプロセス中(キャッシュ、ロック、予約などの目的で)モデルデータを保持することになっています。いかなる状況においても、この状態がモデルデータであってはなりません。

私のアドバイス:あなたの現在の「デザイン」を手放してください。それを修正しようとしないでください、それを正当化しようとしないでください。手放し、コードを削除し、振り返らないでください。EJBに関する優れた本をいくつか読んでから、最初からやり直してください。

幸運を!

于 2012-02-23T09:36:53.803 に答える
1

私はあなたがSFSBとSLSBの使用法で正しい/間違っているかどうかを検証していません。しかし、以下はあなたの問題への答えです

オプション1:サーブレットから、SFSBのJNDIルックアップを実行します。これは1回である必要があります。返されたSFSBの参照をHttpSessionに保存します。ユーザーの詳細を格納するためにSFSBインスタンスを必要とするSLSBメソッドを呼び出す場合は、上記のSFSB参照オブジェクトをパラメーターとしてSLSBメソッドに渡します。次に、SLSBメソッドからアクセスし、ユーザーデータを保存します。

オプション1の問題:永続化メカニズム(SFSB)をUIコードに結び付けています(HttpSessionに保存して渡すため)。明日、キャッシュのような別の永続性メカニズムに変更したい場合は、多くのやり直しを行う必要があります。繰り返しになりますが、SLSBメソッドをWebServiceとして公開する場合は、SFSBオブジェクト参照をxml化できないため、公開できません。要するに、悪いオプションです。

オプション2:ビジネス層の一部のクラスに静的ハッシュマップを設定します。IDのように、すべてのトランザクションに固有のトランザクション属性があると仮定します。トランザクションを開始するときは、ビジネス層からSFSBを作成し、その参照をIDをキーとして静的ハッシュマップに格納します。SLSBサービスメソッドを呼び出すときは、このIDを渡します(各トランザクションは一意のIDを持つことができると思います)。SLSBメソッドから、IDを使用して静的ハッシュマップに格納されているSFSB参照を検索します。ストレージに使用してください。このオプションでは、UIとSFSBは結合されていません。明日、永続化メカニズムを変更したい場合は、変更がBC層内に制限されるため、クライアントに影響を与えることなく実行できます。

于 2012-05-10T15:53:18.167 に答える