Изучаем Java EE 7 - [246]

Шрифт
Интервал


Листинг 15.16. Поставщик, порождающий специальное представление Customer

>@Provider

>@Produces("custom/format")

>public class CustomCustomerWriter implements MessageBodyWriter {

>··@Override

>··public boolean isWriteable(Class type, Type genericType, 

>······Annotation[] annotations, MediaType mediaType) {

>····return Customer.class.isAssignableFrom(type);

>··}

>··@Override

>··public void writeTo(Customer customer, Class type, Type gType, 

>······Annotation[] annotations, MediaType mediaType, 

>······MultivaluedMap httpHeaders, 

>··OutputStream outputStream) throws IOException, WebApplicationException {


>····outputStream.write(customer.getId(). getBytes());

>····outputStream.write('/');

>····outputStream.write(customer.getFirstName(). getBytes());

>····outputStream.write('/');

>····outputStream.write(customer.getLastName(). getBytes());

>··}


>··@Override

>··public long getSize(Customer customer, Class type, Type genericType, 

>······Annotation[] annotations, MediaType mediaType) {

>····return customer.getId(). length() + 1 + customer.getFirstName(). length() 

>········+ 1 + customer.getLastName(). length();

>··}

>}

С другой стороны, для отображения тела запроса на тип Java класс должен реализовывать интерфейс javax.ws.rs.ext.MessageBodyReader и сопровождаться аннотацией @Provider. По умолчанию предполагается, что такая реализация должна применять все медиатипы (*/*). Аннотация @Consumes в листинге 15.17 используется для указания нашего специального медиатипа. Метод readFrom принимает поток данных ввода, размечает его с помощью разделительного символа / и преобразует в объект Customer. Реализации MessageBodyReader и MessageBodyWriter могут генерировать исключение WebApplicationException, если они не способны создать какое-либо представление.


Листинг 15.17. Поставщик, использующий специальный поток данных и создающий объект Customer

>@Provider

>@Consumes("custom/format")

>public class CustomCustomerReader implements MessageBodyReader {

>··@Override

>··public boolean isReadable(Class type, Type genericType, 

>······Annotation[] annotations, MediaType mediaType) {

>····return Customer.class.isAssignableFrom(type);

>··}


>··@Override

>··public Customer readFrom(Class type, Type gType, 

>······Annotation[] annotations, MediaType mediaType, 

>······MultivaluedMap httpHeaders, InputStream inputStream) 

>······throws IOException, WebApplicationException {

>····String str = convertStreamToString(inputStream);

>····StringTokenizer s = new StringTokenizer(str, "/");


>····Customer customer = new Customer();

>····customer.setId(s.nextToken());

>····customer.setFirstName(s.nextToken());

>····customer.setLastName(s.nextToken());


>····return customer;

>··}

>}

Имея CustomCustomerWriter и CustomCustomerReader, мы можем обмениваться данными, представленными в нашем специальном формате. Обмен идет в обоих направлениях между службой и потребителем. Веб-службы в стиле REST должны просто объявлять верный медиатип, а среда времени исполнения JAX-RS сделает остальное:

>@GET

>@Produces("custom/format")

>public Customer getCustomCustomer () {

>··return new Customer("1234", "Джон", "Смит");

>}

Наш пользовательский формат представляет собой особый случай, но при работе с обычными медиатипами реализация JAX-RS применяет несколько стандартных поставщиков объектов (табл. 15.7). Поэтому в наиболее распространенных случаях вам не придется реализовывать собственные механизмы для считывания и записи.


Таблица 15.7. Поставщики, применяемые в реализации JAX-RS по умолчанию
ТипОписание
byte[]Все медиатипы (*/*)
java.lang.StringВсе медиатипы (*/*)
java.io.InputStreamВсе медиатипы (*/*)
java.io.ReaderВсе медиатипы (*/*)
java.io.FileВсе медиатипы (*/*)
javax.activation.DataSourceВсе медиатипы (*/*)
javax.xml.transform.SourceXML-типы (text/xml, application/xml)
javax.xml.bind.JAXBElementМедиатипы для XML, относящиеся к классу JAXB (text/xml, application/xml)
MultivaluedMapСодержимое формы (application/x-www-form-urlencoded)
javax.ws.rs.core StreamingOutputВсе медиатипы (*/*), только с MessageBodyWriter

Обработка исключений

До сих пор мы обсуждали идеальный код, который исправно выполняется всегда и везде и не требует обработки исключений. К сожалению, жизнь не так хороша и рано или поздно вам придется столкнуться со сбоями, происходящими в ресурсах либо из-за получения невалидных данных, либо из-за ненадежности участков сети.

Метод ресурса может генерировать любое проверяемое или непроверяемое исключение. Непроверяемые исключения могут генерироваться повторно, а также проникать в базовый контейнер. Напротив, проверяемые исключения не могут генерироваться непосредственно и должны обертываться в исключения, специфичные для того или иного контейнера (ServletException, WebServiceException или WebApplicationException). Но вы также можете выдавать javax.ws.rs.WebApplicationException или его подклассы (BadRequestException, ForbiddenException, NotAcceptableException, NotAllowedException, NotAuthorizedException, NotFoundException, NotSupportedException). Исключение будет отлавливаться реализацией JAX-RS и преобразовываться в HTTP-ответ. Стандартная ошибка имеет код 500 и соответствует пустому сообщению. Но класс javax.ws.rs.WebApplicationException предлагает различные конструкторы, позволяющие выбрать конкретный код состояния (этот код определяется в перечислении javax.ws.rs.core.Response.Status) или объект. В листинге 15.18 метод getCustomer генерирует непроверяемое исключение (IllegalArgumentException), если идентификатор пользователя меньше 1000, либо код 404 — Не найдено, если запись, соответствующая определенному пользователю, не будет найдена в базе данных. Вместо этого можно было бы также выдать NotFoundException.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.