9

リモートで取得されたマネージドBean(ビュースコープ)からのデータをテーブルに表示するjsfビューがあります。
現在、データは、primefaces ポーリング コンポーネントを使用したクライアント ビューからのポーリングによって更新されます。

大量のトラフィックがクライアントに送信され、primefaces が server-push をサポートするようになったため、これでは十分ではありません。データが変更された場合にのみ、データをリロードしてクライアント ビューにプッシュしたいだけです。

これは、Web 層からアプリケーション層へのポーリングで のようなメソッドを呼び出して実現する必要がありますhasChanged(...)。データが変更された場合、Web 層はクライアントに通知をプッシュしてデータをリロードします。

現在のクライアントの投票

クライアント>> Web 層>>アプリケーション層

クライアントは ajax を介して Web 層にデータを要求し、それが再びアプリケーション層にデータを要求し、ビューを更新します

希望する Web 層のポーリングとプッシュ

クライアント<< Web 層>>アプリケーション層

データが変更された場合は web-tier が app-tier をポーリングし、代わりにリロードし、ビューを更新するようにクライアントに通知 (プッシュ) します。

アプローチ:

Web 層のマネージド Bean でポーリングを実現するための最良のアプローチは何ですか?

  1. マネージド Bean の TimerTask
    タイマーを使用したスケジュールされたタスクの JSF マネージド Bean でのスレッドの生成
  2. Schedule アノテーションを持つ追加の EJB
  3. TimerService を使用した追加の EJB
  4. 他の?

編集:

アーキテクチャ: (3 層)

  • Server1: データベース
  • Server2: アプリケーション層 (リモート EJB + Hibernate を使用する EAR)
  • Server3: Web 層 (JSF 2.0 + Primefaces 3.4 を使用した WAR)
  • クライアント: ブラウザ

建築

4

1 に答える 1

3

私の経験に基づいて、SpringIntegrationとCDIEventsの2つのルートをお勧めします。春のルートをお勧めしますが、現在のスタックに基づいて、CDIイベントでカバーされていると思います。それらは、オブザーバー/オブザーバブルパターンを達成するのにきれいに役立ち、ティアのきれいな分離を引き出すこともできます。ただし、このアプローチは中小規模のユースケースにのみ有効です。次のことを考慮してください。

  1. Event消費者に配信するために必要なすべての情報をカプセル化するクラスを設計および実装します。これをイベントと呼びましょう。FundsTransferイベントの実装には、リスナーが対象のイベントのみをフィルタリングできるようにするための十分な情報が含まれている必要があります。シンプルなPOJO

    class FundsTransfer {
    
        BigDecimal transferValue;
        Date transferDate;
        int transferCurrencyCode;
    
        public FundsTransfer(BigDecimal transferValue, Date date, int currencyCode) {
            //set accordingly
        }
        //setters and getters
    }
    
  2. ビジネス層にビジネスオブジェクトを実装し、それを呼び出しますNotifier。ポーリングの機能は、このオブジェクトに委任する必要があります。eventサーバー側の変更に応じて、タイプのオブジェクトの作成と公開を担当します。要件に応じて、このオブジェクトはすべてのタイプを処理するシングルトンにすることも、さまざまなイベントをポーリングするタイプEventのグループを持つこともできます。Notifier

    //A sample implementation of your Observer object :
    @Singleton //Defines a singleton EJB
    public class PollerService {
    
        @Inject
        Event fundsTranferNotifier;
    
        //this annotation specifies that the polling method should run every second.
        @Schedule(second = "*/1", minute = "*", hour = "*", persistent = false)
        public void pollIt() {
            boolean found = this.pollingMethod(); // pollingMethod() will do the actual polling
            if (found) {     //based on the outcome of the polling method, fire the notifier  method
                blowWhistleOnTransfer();
            }
        }
    
        public void blowWhistleOnTransfer() {
            //this is the broadcast event.
            fundsTransferNotifier.fire(new FundsTransfer(new BigDecimal("100000", new Date(), 855));
        }
    }
    

    上記のコードでは、TimerEJBをオブザーバーとして使用しています。EJBタイマーの概要については、これを参照してください。この場合も、Observerオブジェクトはアプリ層に存在します

  3. クライアント層はそれぞれ、関心のあるイベントが発生したときに通知されるリスナーオブジェクトにアクセスできます(つまり、Notifierタイプによって公開されています)。次に、リスナーはpushこのイベントに基づいてを発行できます。リスナーオブジェクトは、@NamedCDIアノテーション付きのPOJOである可能性があります。リスナーオブジェクトで@Observes、リスナーが関心のあるイベントのタイプのパラメーターを使用して、アノテーションを使用してメソッドを実装するだけです。

    public void onNewTransfer(@Observes FundsTransfer transfer) {
        if (transfer.compareTo(new BigDecimal("150000")) > 0) {
            //push to view.
        }
    }
    

    上記のフィルタリングは、CDIが提供するメッセージフィルタリングオプションと比較すると、まだかなり粗雑です。前に参照したチュートリアルからわかるように、メッセージに対してよりきめ細かいフィルタリングを提供できるCDI修飾子を作成できます。前に述べたように、これは大規模な展開では少し重いです。その場合、依存関係を受け入れる場合は、春の統合ルートをお勧めします。

要約すると、システムのモデルは次のようになります。

            One Poller(Notifier) Object (In the app layer)
                    |
                    |
                    |
            Multiple Listener Objects (In the web tier)
---------------------------------------------------
|   |    |    |    |   |   |     |   |    |    |  |  
于 2012-10-30T05:32:17.027 に答える