如何处理Wicket自定义模型中抛出的异常?

Mar*_*man 4 error-handling wicket

我有一个带有自定义模型的组件(扩展了wicket标准的Model类).当Wicket调用时,我的模型从数据库/ Web服务加载数据getObject().

此查找可能由于多种原因而失败.我想通过在带有组件的网页上显示一条好消息来处理这个错误.最好的方法是什么?

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,错误发生模型内部,该模型与组件分离.

Car*_*zel 7

处理模型的getObject()中发生的异常是棘手的,因为此时我们通常深入到整个请求周期的响应阶段,并且更改组件层次结构为时已晚.因此,处理异常的唯一地方非常非本地,不是在您的组件或模型附近,而是在RequestCycle.

虽然有一种解决方法.我们使用a Behavior和an 的组合IRequestCycleListener来处理这个问题:

  • IRequestCycleListener#onException允许您检查请求期间抛出的任何异常.如果IRequestHandler从此方法返回一个,则将运行并呈现该处理程序,而不是事先发生的任何其他操作.

    我们自己使用它来捕获像Hibernate这样的通用东西StaleObjectException,将用户重定向到通用的"其他人修改你的对象"页面.如果你

  • 对于更具体的情况,我们添加一个RuntimeExceptionHandler行为:

    public abstract class RuntimeExceptionHandler extends Behavior {
        public abstract IRequestHandler handleRuntimeException(Component component, Exception ex);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    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;
          }
        }
      });
    }
    
    Run Code Online (Sandbox Code Playgroud)

    注意:这不是 Wicket附带的东西,我们自己推出.我们简单地结合IRequestCycleListenerBehavior检票的功能,想出这个.


sve*_*ier 6

您的模型可以实现IComponentAssignedModel,从而能够保留拥有的组件.

但我想知道你多久能重复使用MyCustomModel?我知道有些开发人员主张创建独立模型实现(通常在单独的包中).虽然有一些常用的情况(例如FeedbackMessagesModel),但根据我的经验,它更容易创建特定于组件的内部类.