JSON・XMLを返すけどエラー時はステータスコードやメッセージを選びたい
JAX-RSで200とか404とか返すだけなら、メソッド戻り値にResponseを指定してResponseを操作すればいい。
@RequestScoped @Path("myresource") public class MyResource { @GET public Response getIt() { return Response.ok().build(); // 200が返る } }
JSONとかXMLとか返したいなら、戻り値にオブジェクトを指定して@ProducesでMIME(MediaType)を指定する。
@GET @Produces(MediaType.APPLICATION_JSON) public User getIt() { User user = userService.getUser(1); return user; // JSONが返る }
本題。
通常はJSONやXMLを返したいけど、データベースなどにデータが無い場合は404にしたい。
参考:Chapter 7. Representations and Responses
@GET @Produces(MediaType.APPLICATION_JSON) public User getIt() { try { User user = userService.getUser(1); return user; // JSONが返る(ステータスコード:200) } catch (NoResultException e) { throw new WebApplicationException(404); // 404が返る } }
WebApplicationExceptionをthrowする。ステータスコード返すだけならコード番号を渡す。
メッセージも変えたいならResponseを渡す。
throw new WebApplicationException( Response.status(Status.NOT_FOUND).entity("error. error. error.").build() );
長すぎるし。。。
多分、WebApplicationExceptionを継承したクラス作るほうが幸せになれる。
public class CustomException extends WebApplicationException { public CustomException() { super(Response.status(Status.NOT_FOUND).build()); } public CustomException(String message) { this(Status.NOT_FOUND, message); } public CustomException(Status status, String message) { this(status.getStatusCode(), message); } public CustomException(int code, String message) { super( Response.status(code).entity(message).build() ); } }
他にもExceptionMapperを使ってExceptionとレスポンスをマッピングさせる方法もある。
NoResultException -> 404 とかやってもいいけど、エラーの切り分けが面倒になりそう
(データが無いのか、単純にパスが間違っているのか、etc...)
なのでやめておく。
余談
このままだとtext/plainだけど、JSON(XML)返すサービスならエラーもJSON(XML)で返すべき?
まあMediaType指定するだけでいいから何とでもなるんだけど。