4

カスタム モデル (ウィケットの標準モデル クラスを拡張する) を持つコンポーネントがあります。Wicket が を呼び出すと、私のモデルはデータベース/Web サービスからデータをロードしますgetObject()

このルックアップは、いくつかの理由で失敗する可能性があります。コンポーネントを使用して Web ページに素敵なメッセージを表示することで、このエラーを処理したいと考えています。それを行う最善の方法は何ですか?

public class MyCustomModel extends Model {

    @Override
    public String getObject() {
        try {
            return Order.lookupOrderDataFromRemoteService();
        } catch (Exception e) {
            logger.error("Failed silently...");
            // How do I propagate this to the component/page?
        }           
        return null;
}

コンポーネントから分離されたモデルでエラーが発生することに注意してください。

4

5 に答える 5

7

モデルの getObject() で発生する例外を処理するのは難しいです。この時点では通常、リクエスト サイクル全体のレスポンス フェーズに深く入り込んでおり、コンポーネント階層を変更するには遅すぎるからです。そのため、例外を処理する唯一の場所は、ローカルではなく、コンポーネントやモデルの近くではなく、RequestCycle.

ただし、それを回避する方法があります。これに対処するために、 aBehaviorと anの組み合わせを使用します。IRequestCycleListener

  • IRequestCycleListener#onExceptionリクエスト中にスローされた例外を調べることができます。このメソッドからを返すとIRequestHandler、そのハンドラーが実行され、事前に行われていたことの代わりにレンダリングされます。

    これを独自に使用して、Hibernate のような一般的なものをキャッチしStaleObjectException、ユーザーを一般的な「他の誰かがあなたのオブジェクトを変更した」ページにリダイレクトします。もし、あんたが

  • より具体的なケースでは、動作を追加しRuntimeExceptionHandlerます。

    public abstract class RuntimeExceptionHandler extends Behavior {
        public abstract IRequestHandler handleRuntimeException(Component component, Exception ex);
    }
    

    ではIRequestCycleListener、現在のページのコンポーネント ツリーを調べて、コンポーネントに のインスタンスがあるかどうかを確認しますRuntimeExceptionHandler。見つかった場合はそのhandleRuntimeExceptionメソッドを呼び出し、返された場合はそれIRequestHandlerを使用します。このようにして、ページのローカルでエラーを実際に処理することができます。

    例:

    public MyPage() {
      ...
      this.add(new RuntimeExceptionHandler() {
        @Override public IRequestHandler handleRuntimeException(Component component, Exception ex) {
          if (ex instanceof MySpecialException) {
            // just an example, you really can do anything you want here.
            // show a feedback message...
            MyPage.this.error("something went wrong"); 
            // then hide the affected component(s) so the error doesn't happen again...
            myComponentWithErrorInModel.setVisible(false); // ...
            // ...then finally just re-render this page:
            return new RenderPageRequestHandler(new PageProvider(MyPage.this));
          } else {
            return null;
          }
        }
      });
    }
    

    注: これはWicket に同梱されているものではなく、独自のものです。これは、WicketのIRequestCycleListenerと機能を単純に組み合わせたものです。Behavior

于 2012-09-18T11:21:29.880 に答える
6

モデルは IComponentAssignedModel を実装できるため、所有コンポーネントを保持できます。

しかし、MyCustomModel をどのくらいの頻度で再利用できるのだろうか? 一部の開発者は、スタンドアロン モデルの実装 (多くの場合、個別のパッケージ) の作成を推奨していることを知っています。これが役立つ一般的なケース (FeedbackMessagesModel など) もありますが、私の経験では、コンポーネント固有の内部クラスを作成する方が簡単です。

于 2012-09-17T12:59:50.580 に答える
2

ここでModelの主な問題は、 が設計上コンポーネント階層から切り離されていることModelです。特定のコンポーネントに対してすべてのエラーを報告するコンポーネント対応を実装できます。

Detachable関連Componentが分離されるように実装することを忘れないでください。

Modelが高価な操作を実行する場合は、代わりに を使用することに関心があるかもしれません (複数回呼び出される可能性があるLoadableDetachableModelことを考慮してください)。Model.getObject()

public class MyComponentAwareModel extends LoadableDetachableModel { 
    private Component comp;         
    public MyComponentAwareModel(Component comp) { 
          this.comp = comp;
    }

    protected Object load() {
        try {
            return Order.lookupOrderDataFromRemoteService();
        } catch (Exception e) {
            logger.error("Failed silently...");
            comp.error("This is an error message");
        }           
        return null;
    } 

    protected void onDetach(){
        comp.detach();
    }
}

代わりに試してみる価値があるかもしれませんSession.get().error())

于 2012-09-17T11:36:41.930 に答える
0

ページに FeedbackPanel を追加し、catch 句で error("some description") を呼び出します。

于 2012-09-17T09:25:50.790 に答える
0

で単純に null を返しgetObject、コントローラー クラスにロジックを追加して、 nullgetObjectが返された場合にメッセージを表示することができます。

さまざまな失敗の理由でカスタム メッセージが必要な場合String errorMessage;は、例外をキャッチするときに設定されるモデルのようなプロパティを追加できgetObjectます。これにより、コントローラー クラスで次のようなことができます。

if(model.getObject == null) {
 add(new Label("label",model.getErrorMessage()));
} else {
 /* display your model object*/
}
于 2012-09-17T13:11:26.677 に答える