Dropwizard何もしないと指定したURLに対応するページがない場合、
Jersey404 エラーページがデフォルトのまま出力されます。
このエラーページを変えたかったのですが、Wicketとの組み合わせでの出し方がわからず、
ハマって、2-3日途方に暮れていました..
出力の仕方をメモします。

素のWicketでのエラーページの設定方法

こちら記載がありますが、
以下の手順を踏むと、404発生時のエラーぺージを設定できます。

1. Web.xmlerror-page定義を追加する。

2. 404エラー用のPageクラスを作成する。

3. Applicationクラス内で対象ページmountPageする。


Dropwizard起動からのWicketでのエラーページの設定方法

Web.xml設定がDropwizardからだとできず(できたとしてもやりたくはない)、
以下のように設定しました。
そもそも、DropwizardからWicket起動するにはこちら参照ください。

1. WicketBundle内で、ErrorPageErrorHandler設定する。

  • WicketBundle#(run)メソッド内でcontext.setErrorHandler()実行する。

    @Override
    public void run(WicketConfiguration configuration, Environment environment) throws Exception {
        MutableServletContextHandler context = environment.getApplicationContext();
        context.addEventListener(new GuiceServletConfig());
        FilterHolder filterHolder = getFilterHolder(configuration.isDeployment());
        context.addFilter(filterHolder, "/*", DISPATCHER_TYPES);
        // Comment
        context.addServlet(DefaultServlet.class, "/*");

        // Set ErrorHandler
        ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler();
        errorHandler.addErrorPage(404, "/404");
        context.setErrorHandler(errorHandler);

        // Set SessionHandler
        context.setSessionHandler(new SessionHandler());

        environment.jersey().disable();
    }

  • org.eclipse.jetty.servlet.ErrorPageErrorHandlerついて
    こちらには、以下のようなメソッドが存在します。

    • void addErrorPage (Class exception, String uri)
    • void addErrorPage (int code, String uri)
    • void addErrorPage (int from, int to, String uri)

Web.xmlerror-page記述と同等の設定を行うことができます。
デフォルトは、org.eclipse.jetty.servlet.ErrorHandler動作しているのかと思いますが、
こちらは、エラー画面用のHTMLクラス内に書きつけられていて、それが出力されるようです。

2. 404エラー用のPageクラスを作成する。

  • エラーPageの抜粋です。

package xyz.monotalk.xxx;

import javax.servlet.http.HttpServletRequest;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.protocol.http.servlet.ErrorAttributes;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.request.mapper.parameter.PageParameters;

/**
 * ErrorPage
 *
 * @author Kem
 */
public class ErrorPage {

    private static final long serialVersionUID = -5540046731407875758L;

    @Override
    protected void initPage(PageParameters parameters) {
        // Get ErrorAttributes
        ErrorAttributes errorAttributes = getErrorAttributes();
        // Add ErrorMessage
        add(new Label("errorMessage", errorAttributes.getStatusCode() + " " + errorAttributes.getMessage())
                .setRenderBodyOnly(true));
        // Add Top page Link
        BookmarkablePageLink link = new BookmarkablePageLink<>("topLink", getApplication().getHomePage());
        link.add(new Label("topLinkText", "Top Page"));
        add(link);
    }

    // getHttpServletRequest
    private ErrorAttributes getErrorAttributes() {
        // Get ErrorAttributes
        ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
        HttpServletRequest request = servletWebRequest.getContainerRequest();
        return ErrorAttributes.of(request, "/");
    }

    @Override
    protected void configureResponse(WebResponse response) {
        super.configureResponse(response);
        response.setStatus(getErrorAttributes().getStatusCode());
    }

    @Override
    public boolean isVersioned() {
        return false;
    }

    @Override
    public boolean isErrorPage() {
        return true;
    }
}

指定されたURLなかった場合も、
Pageクラス内で、AbortWithHttpErrorCodeException404エラーを送出した場合も、
エラーぺージクラス内では、javax.servlet.error.status_codejavax.servlet.error.message で、
エラー情報が取得できたので、org.apache.wicket.protocol.http.servlet.ErrorAttributes使用して、
エラー情報を取得、その情報を画面に出力するようにしました。
ただ、404しか辿り着くことはないので、メッセージが切りわかる機能が追加されたなのですが

3. Applicationクラス内で対象ページmountPageする。

3.実施することは同じです。


補足

ソフト404エラーぺージ

Error Pages and Feedback Messages - Apache Wicket - Apache Software FoundationExampleに記述されている

@Override
protected void configureResponse() {
    super.configureResponse();
    getWebRequestCycle().getWebResponse().getHttpServletResponse().setStatus(HttpServletResponse.SC_NOT_FOUND);
}

を記載しないと、
Googleウェブマスターツールが「ソフト404」をレポート表示 | 海外SEO情報ブログ
ソフト404エラーページになるので、外部公開するときは明示的に記載が必要になりそうです。

ただ、URLMountされていない場合の404は、記載がなくても404になるので、その用途のみに使うなら不要です。
Wicket内部でエラー発生時に遷移させる場合は、明示的に記載が必要になります。

以上です。

コメント

カテゴリー