1

Seam を初めて使用するので、依存関係の注入に問題があります。間違った方法で何かをしている可能性があります。

コントローラー内から起動される新しいスレッドに依存関係を注入する必要があります-例外は発生しませんが、単に発生しますnull。最初に、スレッド内で単純に再利用しようとしd1ましたが(以下を参照)、nullこのオブジェクトに再び注釈を付けるというアイデアがありました@In...残念ながら同じことが起こりました(nullになりました)!!!

@Scope(ScopeType.CONVERSATION)
@Name("myController")
public class MyController{
    @In(create = true)
    private Dependency1 d1; //ok, gets injected with no problems!

    public void importantMethod(){
        //this part of the method is important and is fast
        //but below comes an expensive part that takes some minutes

        new Thread(new Runnable(){
            @In(create = true)
            private Dependency1 anotherD1;  //I still need d1 here!!!       

            @Override
            public void run(){
                //I want to run expensive code here.
                //A new thread is required in order to leave
                //the visitor free to go else where on the web site

                //First trial was to make d1 final and simply use it here!
                //d1.doExpensiveStuff();
            };
        }).start();
    }
}

なぜこれが起こっているのか誰にも分かりますか?DI/Seam/Threading を使用する際の良い方法はありますか?

4

1 に答える 1

5

インジェクションは次の場合にのみ発生します。

  1. Seam コンポーネント (あなたの例では、コンポーネントであり、内部で作成MyControllerする匿名はコンポーネントではありません)。Runnable
  2. Seam ライフサイクル内。ライフサイクルは、JSF リクエスト、非同期実行、または手動で開始されます。

@Inスレッドはコンポーネントではなく、Seam はその呼び出しをインターセプトしないため、スレッド内で使用することはできません。非同期スレッド内のコンポーネントを取得するには、Seam API を使用してライフサイクルを開始し、必要なコンポーネントを取得する必要があります。

@Scope(ScopeType.CONVERSATION)
@Name("myController")
public class MyController {

    @In(create = true)
    private transient Dependency1 d1;

    public void importantMethod() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                LifeCycle.beginCall(); // Start the Seam lifecycle
                Dependency1 d1 = (Dependency1) Component.getInstance("dependency1");
                d1.doExpensiveStuff();
                LifeCycle.endCall();   // Dispose the lifecycle
            }
        }).start();
    }
}

Seam は、@Asynchronousここで必要なことだけを行うアノテーションを提供します。このアノテーションが Seam コンポーネントのメソッドで使用される場合、メソッドは (Seam 所有のスレッドプールから取得された) バックグラウンドスレッドで実行されます。非同期メソッドは、注入された依存関係を通常の Seam 呼び出しのように使用できることに注意してください。

@Name("myBackgroundWork")
public class MyBackgroundWork {
    @In private transient Dependency1 d1;

    @Asynchronous
    public void runInBackground() {
         d1.doExpensiveStuff();
    }
}

次にMyController、バックグラウンド作業を開始してすぐに戻る非同期メソッドを呼び出すことができます。

@Scope(ScopeType.CONVERSATION)
@Name("myController")
public class MyController {
    @In(create = true)
    private MyBackgroundWork myBackgroundWork;

    public void importantMethod() {
        // Execution will return immediately and thread will start
        myBackgroundWork.runInBackground();
    }
}

詳細はこちら:

http://docs.jboss.org/seam/2.2.2.Final/reference/en-US/html/jms.html#d0e21609

于 2012-10-05T10:31:00.257 に答える