概要
REST APIアプリにて、web.xmlを使用して例外ハンドリングを行う方法についてまとめた。
概要 REST APIアプリにて、入力チェックを行った際のエラーハンドリング方法についてまとめた。 エラーメッセージはBean Validationのデフォルトメッセージを使用する。
Webアプリケーションの設定
例外がアプリ側でハンドリングされず、サーブレットコンテナ(Tomcat)まで伝播する場合、web.xmlを利用して例外ハンドリングを行う。
web.xml
例外の種類に応じて、エラー時の挙動を設定できる。
今回は特定のエラー情報がサーブレットコンテナまで伝播した場合、「/error」にフォワードさせる。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<!-- WebアプリケーションコンテキストのDIコンテナ作成 -->
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/spring/springMVCContext.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- ルートアプリケーションコンテキストのDIコンテナ作成 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/spring/applicationContext.xml
</param-value>
</context-param>
<!-- HTTP 500 エラーページを指定 -->
<error-page>
<error-code>500</error-code>
<location>/error</location>
</error-page>
<!-- NullPointerException が発生した場合に /error へリダイレクト -->
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error</location>
</error-page>
<!-- デフォルトエラーハンドリング -->
<error-page>
<location>/error</location>
</error-page>
</web-app>
<error-page>
<error-code>500</error-code>
<location>/error</location>
</error-page>
上記はHTTPステータスコード500がサーブレットコンテナまで伝播した場合、「/error」にフォワードする。
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error</location>
</error-page>
上記はNullPointerExceptionがサーブレットコンテナまで伝播した場合、「/error」にフォワードする。
<error-page>
<location>/error</location>
</error-page>
上記はアプリ側でハンドリングされなかった、あらゆる例外がサーブレットコンテナまで伝播した場合に「/error」にフォワードする。
コントローラークラス
「/error」に対応したハンドラメソッドを保持するクラス。
ApiErrorHandleController.java
package com.example.rest_prototype.web.controller.error;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.rest_prototype.web.resources.error.ErrorInfo;
import com.example.rest_prototype.web.resources.error.ValidateErrorInfo;
/**
* REST APIにてweb.xmlで例外ハンドリングする
* 共通エラーコントローラーにリクエストさせる
*/
@RestController
public class ApiErrorHandleController {
@GetMapping(value = "/error")
public ResponseEntity<ErrorInfo> handleError(HttpServletRequest req) {
Integer status = (Integer) req.getAttribute("javax.servlet.error.status_code");
HttpStatus httpStatus = HttpStatus.resolve(status != null ? status : HttpStatus.INTERNAL_SERVER_ERROR.value());
var errorInfo = new ValidateErrorInfo();
errorInfo.setStatus(httpStatus.value());
errorInfo.setErrorCode("SAMPLE_ERR0003");
errorInfo.setErrorTitle("エラー");
errorInfo.setErrorMsg("処理続行不能");
// ResponseEntity を作成して返却
return new ResponseEntity<>(errorInfo, httpStatus);
}
}
public ResponseEntity<ErrorInfo> handleError(HttpServletRequest req) {
サーブレットコンテナにエラーが伝播すると、このコントローラークラスにフォワードする。
ここで任意のエラーメッセージを返却する。
まとめ
☑ アプリ側でハンドリングされていない例外は、サーブレットコンテナ(Tomcat)まで伝播する
☑ web.xmlを使用することで、サーブレットコンテナまで伝播した例外をハンドリングできる
☑ 例外の種類に応じたハンドリングが可能(基本的には@ControllerAdvceでハンドリングすることが推奨される)