Одной из приятных особенностей работы с JEE является то, что доступные компоненты действительно довольно стандартны. При использовании JAX-RS иногда необходимо контролировать, как исключения обрабатываются и передаются пользователю. Если выдается исключение, по умолчанию вы получаете ужасное исключение внутреннего сервера HTTP 500, которое раскрывает внутренние сбои вашего веб-сервиса.
Рассмотрим следующую суть: эта конечная точка будет использоваться для просмотра пользователя на основе идентификатора.
|
1
2
3
4
5
6
7
8
9
|
@Path("/users")public interface UserWebService { @POST @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Path("/{userId}") Response getUser(@PathParam("userId") String userId);} |
Теперь реализация этого интерфейса будет выглядеть примерно так, чтобы сделать работу осла по фактическому извлечению пользователя.
|
01
02
03
04
05
06
07
08
09
10
|
public final class UserWebServiceImpl implements UserWebService { @EJB private UserDao userDao; public Response getUser(final String userId) { final User user = userDao.getUser(userId); return Response.ok().entity(user).build(); }} |
Это выглядит хорошо, но подумайте, если userDao делал какую-то бизнес-логику сущности, используя Query.getSingleResult, а пользователь с таким ID не существовал?
Согласно документации JEE6 API, вы получите NoResultException , что приведет к ошибке HTTP 500, выставляющей исключение вашего внутреннего сервера, что, безусловно, не должно видеть конечный пользователь. Нам нужно использовать обработку исключений Jax-RS!
Во-первых, нам нужен тупой объект исключения с соответствующим именем, который будет тем, что мы на самом деле бросим, рассмотрим код ниже ..
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
public class UserWebServiceException extends Exception implements Serializable { private static final long serialVersionUID = 1169426381288170661L; public UserWebServiceException() { super(); } public UserWebServiceException(String msg) { super(msg); } public UserWebServiceException(String msg, Exception e) { super(msg, e); }} |
Затем нам нужно изменить наш исходный код, чтобы учесть это исключение. Ниже я соответствующим образом изменил исходный UserWebService и соответствующую реализацию.
|
1
2
3
4
5
6
7
8
9
|
@Path("/users")public interface UserWebService { @POST @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Path("/{userId}") Response getUser(@PathParam("userId") String userId) throws UserWebServiceException;} |
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public final class UserWebServiceImpl implements UserWebService { @EJB private UserDao userDao; public Response getUser(final String userId) throws UserWebServiceException { try { final User user = userDao.getUser(userId); } catch(NoResultException e) { throw new UserWebServiceException("User does not exist with id " + userId); } return Response.ok().entity(user).build(); }} |
Теперь это вызовет соответствующее исключение, когда пользователь не может быть найден. Однако нам все еще нужно создать объект Handler, чтобы преобразовать это исключение в реальный ответ JSON, чтобы мы получили приятное дружеское сообщение об ошибке. Класс ниже обрабатывает это исключение и преобразует сообщение об ошибке в исключении в ответ JSON. Важная аннотация этого класса — аннотация @Provider .
|
01
02
03
04
05
06
07
08
09
10
11
|
@Providerpublic final class UserWebServiceExceptionHandler implements ExceptionMapper<UserWebServiceException> { @Override public Response toResponse(final UserWebServiceException exception) { return Response.status(Status.BAD_REQUEST) .entity(new ErrorMessage(exception.getMessage()) ).type(MediaType.APPLICATION_JSON).build(); } } |
Вы заметите, что мы создаем объект ErrorMessage для ответа от веб-службы. Это просто простой тупой объект для хранения сведений о фактической ошибке, которая будет передана в JSON.
|
01
02
03
04
05
06
07
08
09
10
11
|
public class ErrorMessage { private String error; public ErrorMessage(String error) { this.error = error; } public String getError() { return error; }} |
Последний шаг в сопоставлении нашего поставщика обработчика исключений с веб-приложением заключается в добавлении следующего в наш web.xml для нашего веб-приложения.
|
1
2
3
4
|
<context-param> <param-name>resteasy.providers</param-name> <param-value>uk.co.soa.rest.providers.UserWebServiceExceptionHandler</param-value> </context-param> |
Теперь, когда мы вызываем эту конечную точку REST с несуществующим идентификатором пользователя (скажем, «DAG»), мы с радостью получим следующий ответ JSON, а не трассировку стека.
|
1
2
3
|
{ "error": "User does not exist with id DAG"} |
| Ссылка: | Пользовательская обработка исключений Jax-RS от нашего партнера JCG Дэвида Грея из блога Code Mumble . |