Dropwizard
は何もしないと指定したURLに対応するページがない場合、
Jersey
の404 エラーページがデフォルトのまま出力されます。
このエラーページを変えたかったのですが、Wicket
との組み合わせでの出し方がわからず、
ハマって、2-3日途方に暮れていました..
出力の仕方をメモします。
素のWicket
でのエラーページの設定方法
こちらに記載がありますが、
以下の手順を踏むと、404発生時のエラーぺージを設定できます。
1. Web.xml
にerror-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.xml
のerror-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
クラス内で、AbortWithHttpErrorCodeException
で404エラーを送出した場合も、
エラーぺージクラス内では、javax.servlet.error.status_code
、javax.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 FoundationのExampleに記述されている
@Override
protected void configureResponse() {
super.configureResponse();
getWebRequestCycle().getWebResponse().getHttpServletResponse().setStatus(HttpServletResponse.SC_NOT_FOUND);
}
を記載しないと、
Googleウェブマスターツールが「ソフト404」をレポート表示 | 海外SEO情報ブログの
ソフト404エラーページになるので、外部公開するときは明示的に記載が必要になりそうです。
ただ、URL
がMount
されていない場合の404は、記載がなくても404になるので、その用途のみに使うなら不要です。
Wicket内部でエラー発生時に遷移させる場合は、明示的に記載が必要になります。
以上です。
コメント