AjaxButton#onSubmit()にて、Exception 発生時に、
AjaxButton#onError(AjaxRequestTarget target, Form<?> form) 処理の制御が移らず、
うまくハンドリングができておりません。
ハンドリングできていない理由を調べてみました。
参考
-
wicket/LinksPage.java at master · apache/wicket
Wicket の Example ずばりそのものなサンプルがあります。 -
9 Under the hood of the request processing 6.x
Ajax requests
に、AjaxErrorStrategy
の説明があります。
そもそも、onSubmit()でエラーが発生したら、onError() は実行されない。
onError()は実行されない動作をするものでした。1
[1] 私が勝手に勘違いをしていただけとなります。
そのため、以下のように Exception 発生時にハンドリングを行う必要があります。2
[2] 引数同じなので、Exception が発生したら、onError を呼び出すでもいいかもしれません。
AjaxButton sendMessage = new AjaxButton("sendMessage", Model.of(getString("messageButtonLabelText"))) {
private static final long serialVersionUID = -8204140666393922700L;
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
try {
// メール送信要求を登録
ContactMailTaskManage contactMailTaskManage = (ContactMailTaskManage) form.getModelObject();
// 内部でJPA呼び出し、ここで、PersistenceExceptionが発生する可能性がある。
mailTaskService.execute(contactMailTaskManage);
} catch (PersistenceException e) {
log.error("Mail transmission failed.", e);
// エラーメッセージを表示して処理を終了
error(getString("messageMailSendError"));
target.add(form);
return;
}
// Formに対してのオペレーション
token.regenerateToken();
success(getString("messageMailSendSucceed"));
target.add(form);
}
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
// AjaxButton は (というかButtonは) setOutputMarkupId(true) なので、特に呼び出さなくてOK
final AjaxCallListener ajaxCallListener = new AjaxCallListener();
ajaxCallListener.onPrecondition("return confirm('" + getString("messageMailSendConfirm") + "');");
ajaxCallListener.onBeforeSend("$('#" + getMarkupId() + "').prop('disabled',true);");
ajaxCallListener.onComplete("$('#" + getMarkupId() + "').prop('disabled',false);$('#" + getMarkupId() + "').focus();");
attributes.getAjaxCallListeners().add(ajaxCallListener);
}
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
error(getString("messageMailSendError"));
target.add(form);
}
};
ExceptionSettings#setAjaxErrorHandlingStrategy() でAjax Error時の振る舞いを変更する。
Application クラスで、
getExceptionSettings().setAjaxErrorHandlingStrategy(ExceptionSettings.AjaxErrorStrategy.INVOKE_FAILURE_HANDLER);
[3] デフォルトの振る舞いは、AjaxErrorStrategy.REDIRECT_TO_ERROR_PAGE で通常リクエストと同じ、ErrorPageに遷移します。
AjaxButton で updateAjaxAttribute 内で、AjaxRequestAttributes#onFailre() で、
失敗時のjavascriptを定義すると、Exception発生時に、そのjavascriptが呼び出されます。
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
// AjaxButton は (というかButtonは) setOutputMarkupId(true) なので、特に呼び出さなくてOK
final AjaxCallListener ajaxCallListener = new AjaxCallListener();
ajaxCallListener.onPrecondition("return confirm('" + getString("messageMailSendConfirm") + "');");
ajaxCallListener.onBeforeSend("$('#" + getMarkupId() + "').prop('disabled',true);");
// 失敗時のjavascriptの定義
ajaxCallListener.onFailure("alert('onFailure');");
ajaxCallListener.onComplete("$('#" + getMarkupId() + "').prop('disabled',false);$('#" + getMarkupId() + "').focus();");
attributes.getAjaxCallListeners().add(ajaxCallListener);
}
どちらで実装を進めるか.
個人的には、デフォルトAjaxErrorStrategy.REDIRECT_TO_ERROR_PAGE
でよいかと思いました。
個別でコントロールできたらよさそうに思いましたが、何か設定があったりするのかもしれません。
以上です。
コメント