2011-12-13 13 views
2

Java EEに関する知識はあまりなく、現在学習中です。Java EE WebApp + icefacesで長時間実行されるタスク

私は、ユーザーによって呼び出される長時間の作業(最大数分間)を伴うプロジェクトを考え出しました。タスクはいくつかのステップで構成されています。もちろん、ユーザーに進捗状況を示したいと思います。

このプロジェクトでは、JPA、JSF、IcefaceでJava EEを使用しています。それはグラスフィッシュで実行されます。

経験豊富な同僚は私に次のパターンをadviced:

  1. 応答オブジェクトを作成し、
  2. が各ステップ
  3. 後に応答オブジェクトを永続化要求を処理するステートレス、非同期EJBの作成応答オブジェクトをクエリして表示する

これはうまくいきます。私の唯一の問題は、進行状況を反映するようにステータスサイトを更新することです。現在、私はx秒ごとに簡単なJavaScriptページをリロードしてこれをやっています。

ステートレスejbからjsfバッキングBeanへの現在のステップを反映するための方法やパターンを知っていますか? また、x秒ごとにバッキングBeanの値を照会する方法を知っていますか?

編集:

私はメカニズムを押しICEfacesをを認識していますが、私はステータス更新サイトは、以下の理由で計算EJBから切り離すことにしたい。

  • バッキングBeanがありますユーザーがサイトを離れて後で結果を取得するために戻ってきたために既に破棄されています
  • 複数のセッションがあるため、1人のユーザーに複数のBeanが存在する可能性があります
  • クリーンデザイン

答えて

1

この情報を返すためのオプションがいくつかあります。 EJBが同じJVM内にある場合、 いくつかのシングルトンマップを使用して、特定のキー(セッションID)で進行状況を保存することもできます。

これが当てはまらない場合は、共有状態または作業が必要になります。 ( - よりよい解決策のRedisのように、キーと値のストアになります - あなたはそれを得た場合は、SQL、JNDI、LDAP)が

  • 堆積するために、いくつかのメッセージングを使用し、いくつかのオプションは、両方の層からアクセス可能なデータベースに格納それを

    • ありますEJB層側のハッシュそれでWeb層側
    • ストア状態での処理の状態、およびその状態をrtrieveするために、別のSLSB方法を提供

    あなたの選択は容易ではない - さまざまな方法をサッキンこれらのソリューションのすべて。

  • 0

    アイソフェイスを使用しているので、更新をレンダリングするのにICEpushメカニズムを使用できます。

    +0

    もちろん、残念ながら私は進捗状況を裏づけしているBeanに通知するメカニズムを知らない。バッキングBeanはすでに破棄されている可能性があります。ユーザーは計算が終了したときに後で戻ってくるでしょう。カプセル化のために、EJBにアイソフェイスコードは必要ありません。 – Michael

    0

    これは、ProgressBarコンポーネントと一緒にスレッドポーリングモデルを使用してこれを実現しました。

    public void init() 
    { 
        // This method is called by the constructor. 
        // It doesn't matter where you define the PortableRenderer, as long as it's before it's used. 
        PushRenderer.addCurrentSession("fullFormGroup"); 
        portableRenderer = PushRenderer.getPortableRenderer(); 
    } 
    
    
    public void someBeanMethod(ActionEvent evt) 
    { 
        // This is a backing bean method called by some UI event (e.g. clicking a button) 
        // Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render 
    
        copyExecuting = true; 
    
        // Create a status thread and start it 
    
        Thread statusThread = new Thread(new Runnable() { 
         public void run() { 
         try { 
             // message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call 
          message = "Copying..."; 
          // initiates render. Note that this cannot be called from a thread which is already part of an HTTP request 
          portableRenderer.render("fullFormGroup"); 
          do { 
           progress = getProgress(); 
           portableRenderer.render("fullFormGroup"); // render the updated progress 
           Thread.sleep(5000); // sleep for a while until it's time to poll again 
          } while (copyExecuting); 
          progress = getProgress(); 
          message = "Finished!"; 
          portableRenderer.render("fullFormGroup"); // push a render one last time 
         } catch (InterruptedException e) { 
          System.out.println("Child interrupted."); 
         } 
        }); 
        statusThread.start(); 
    
        // create a thread which initiates script and triggers the termination of statusThread 
        Thread copyThread = new Thread(new Runnable() {   
         public void run() { 
         File someBigFile = new File("/tmp/foobar/large_file.tar.gz"); 
          scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread 
          copyExecuting = false; // this will caue the statusThread's do..while loop to terminate 
    
    
         } 
        }); 
        copyThread.start(); 
    } 
    
    関連する問題