読者です 読者をやめる 読者になる 読者になる

Jersey Grizzly で始める JAX-RS 入門 〜STEP5〜

Java JavaEE

前回からの続き。

例外ハンドリング

アプリケーションからスローされた WebApplicationException およびそのサブクラスはJAX-RSのコンテナによりキャッチされ、例外に応じたレスポンスが返却されます。

レスポンスは WebApplicationException クラスの getResponse() メソッドにて生成されます。

public class WebApplicationException extends RuntimeException {

    public Response getResponse() {
        return response;
    }
}


以下のように WebApplicationException 以外の例外がスローされた場合

    @GET
    @Path("{id}")
    @Produces({MediaType.APPLICATION_JSON})
    public Customer get(@PathParam("id") Long id) {
        Customer customer = Ebean.find(Customer.class, id);
        if (customer == null)
            throw new RuntimeException("error.");
        return customer;
    }

例外はアプリケーションサーバ側まで伝搬します。 今回の例では Grizzlyにより以下のようなレスポンス(500)が返却されることになります。

f:id:Naotsugu:20160416123914p:plain

定義済み例外

JAX-RX の API では WebApplicationException のサブクラスとして以下の例外が定義されています。

例外 HTTPステータス
BadRequestException 400
ForbiddenException 403
InternalServerErrorException 500
NotAcceptableException 406
NotAllowedException 405
NotAuthorizedException 401
NotFoundException 404
NotSupportedException 415
ServiceUnavailableException 503
ServerErrorException 5XX
RedirectionException 3XX

必要に応じてこれらの例外を使うことができます。

ExceptionMapper

WebApplicationException 及びそのサブクラス以外の例外を扱いたい場合は javax.ws.rs.ext.ExceptionMapper を定義してJAX-RXコンテナに登録します。

ExceptionMapper は以下のようなインターフェース定義となっています。

public interface ExceptionMapper<E extends Throwable> {
    Response toResponse(E exception);
}

E としてこの ExceptionMapper がハンドリングする例外を指定します。

例えば JPA の例外である javax.persistence.EntityNotFoundException をハンドリングしたい場合は以下のような ExceptionMapper を定義します。

package example.web.resource;

import javax.persistence.EntityNotFoundException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

@javax.ws.rs.ext.Provider
public class EntityNotFoundExceptionMapper implements  ExceptionMapper<EntityNotFoundException> {
    public Response toResponse(EntityNotFoundException exception) {
        return Response.status(Response.Status.NOT_FOUND).build();
    }
}

アプリケーション側で以下のように例外をスローした場合、

        if (customer == null) {
            throw new EntityNotFoundException();
        }

EntityNotFoundExceptionMapper が例外をハンドリングして以下のように 404 が返却されるようになります。

f:id:Naotsugu:20160416123801p:plain

なお、main.java にて example.web.resource をリソースのスキャン対象としているため、ExceptionMapper を別パッケージに格納する場合にはスキャン対象の追加が必要となります。

    public static class RsResourceConfig extends ResourceConfig {
        public RsResourceConfig() {
            packages("example.web.resource");
        }
    }

ここまでのソースはGithubを参照してください。