Project Zero - это проект IBM-инкубатора (EN), концентрирующийся на динамичной (agile) разработке Web 2.0-приложений, следующих архитектуре SOA (Service-Oriented Architecture - сервис-ориентированная архитектура). Применение Web 2.0 с SOA позволяет Web-артефактам расширять область действия SOA. Рассматривайте его как SOA, распространенную на Web.
Распространенная на Web SOA представляет собой подмножество SOA, основанное на HTTP-протоколе (Hypertext Transfer Protocol) и на базовых принципах RESTful. Такая SOA рекомендует использовать шаблоны проектирования, которые привели Web к успеху, поэтому для общего блага имеет смысл следовать именно такому подходу при проектировании приложений. К преимуществам относятся:
- Масштабируемость через кэширование и взаимодействия без запоминания состояния.
- Простота, с предварительными требованиями, обычно заключающимися в синтаксическом анализе и визуализации HTTP и XML или JavaScript Object Notation (JSON).
- Широко распространяемый "сетевой эффект" от общих стандартов; например, сайты могут потреблять или агрегировать фиды Atom или RSS, не имея понятия о деталях содержимого.
Цели Project Zero являются как техническими, так и социальными. Технические цели - обеспечить масштабируемую платформу, упрощающую разработку приложений в контексте трех важных аспектов:
- Создание
- Упростить разработку, благодаря поддержке языков написания сценариев (в настоящее время Groovy и PHP), соглашениям, продвигающим RESTful-шаблоны, и каталогам повторно используемых ресурсов.
- Компоновка
- Разрешить быстрый доступ и агрегацию различных сервисов в унифицированные приложения, включая потоки данных, механизмы оркестровки (orchestration) и специализированные модули-посредники (mediation).
- Развертывание
- Предоставить сконцентрированную вокруг приложения среду времени исполнения, основанную на хорошо известной стабильной JVM (Java™ Virtual Machine – виртуальная машина Java) и оптимизированную для динамичной разработки (маленький объем, быстрый перезапуск).
Социальные цели связаны с самим процессом разработки. Zero будет создаваться открыто как коммерческая разработка, управляемая сообществом (Community-Driven Commercial Development - CD/CD). Сообщество пользователей сможет обсуждать и влиять на технические решения для Zero. Пользователи также будут иметь прямой доступ к группе разработчиков Zero и самому исходному коду. Такой уровень прозрачности разработки коммерческого программного обеспечения является новым для IBM; мы надеемся, что это даст очень эффективный результат.
В соответствии с CD/CD вся информация о Zero доступна на сайте www.projectzero.org. В данной серии статей новая информация о Zero не рассматривается, а приводится структурированное введение в концепции проекта.
Понятие REST описывает шаблон проектирования для реализации сетевых систем. REST не является ни технологией, ни стандартом; это архитектурный стиль предоставления ресурсов через Web. Архитектура RESTful придерживается нескольких принципов:
- Запросы являются запросами клиент-сервер и по природе используют стиль взаимодействия, основанный на извлечении информации. Потребляющие компоненты извлекают представления состояния с сервера.
- Запросы являются не сохраняющими состояния. Каждый запрос от клиента к серверу должен содержать всю информацию, необходимую для понимания запроса, и не пользуется каким-либо сохраненным контекстом на сервере.
REST не обязательно означает отсутствие состояния на промежуточном уровне; просто заполнение запроса для ресурса не зависит от этого состояния.
- Клиенты и сервер придерживаются унифицированного интерфейса. Ко всем ресурсам доступ осуществляется через общий в мире архитектуры SOA, распространенной на Web, интерфейс - HTTP с использованием HTTP-методов
GET,POST,PUT,DELETE. - Клиенты обращаются к именованным ресурсам. Система содержит ресурсы, поименованные с использованием URL, например, HTTP URL.
REST - это основная технология для представления сервисов в Web. Важно понимать, что REST работает наилучшим образом при отображении сервисов, основанных на данных. Эти сервисы данных можно затем смешать и согласовать для создания новых приложений (часто называемых mashup). В следующем примере показано, как клиент видит RESTful-сервис.
http://<host>/customer:
- GET: возвращает список клиентов
- POST: создает запись Customer
http://<host>/customer/roland:
- GET: возвращает запись о клиенте Roland
- PUT: обновляет запись о Roland
- DELETE: удаляет запись о Roland
В этом примере отображаемым ресурсом является Customer. Customer представлен URI-адресом /customer. Конкретные клиенты представляются добавлением идентификатора к Customer, например, /customer/ims. Методы HTTP-заголовка определяют цель доступа к ресурсу.
Основные концепции программирования Project Zero
Project Zero - это основание новой специализированной платформы, объединяющей Web 2.0 и SOA для поддержки основанных на Web бизнес-приложений следующего поколения. В данном разделе рассматриваются некоторые базовые концепции. Более подробная информация об этих концепциях приведена в "Руководстве разработчика Project Zero" (см. раздел "Ресурсы").
Сценарии и Java в качестве системных языков
Главной тенденцией упрощения разработки являются языки сценариев. Цель Zero - помочь уменьшить накладные расходы на разработку сервисов, предоставляя упрощенные интерфейсы прикладного программирования (Aapplication Program Interface - API) вокруг сценариев. Языком сценариев по умолчанию является Groovy, основанный на Java и позволяющий Java-программистам легко перейти на него. Через модуль расширения Project Zero поддерживает также PHP.
Zero - это система, основанная на событиях. Все основное поведение системы отображается приложению как набор событий с соответствующим их состоянием. Основной вашей задачей (как разработчика) является предоставление набора обработчиков, перехватывающих хорошо известные системные события для достижения заданного поведения приложения. Стандартные события Zero - это значимые действия, представляющие интерес для приложения.
Например, HTTP-запрос через систему будет генерировать набор событий, для которых разработчик может написать обработчики. На рисунке 1 показана эта концепция с возможностями перехвата событий для обработки аспектов системы защиты или события конкретного HTTP-метода (GET | POST) (более подробная информация по обработке событий приведена в разделе "Руководства разработчика Project Zero", посвященном обработке событий).
Рисунок 1. События
Обработчики событий в Project Zero не имеют явных входных и выходных параметров, таких как request и response. Поскольку все обработчики событий в Project Zero не могут запоминать состояние переменной между активизациями и являются, следовательно, не сохраняющими состояния, Project Zero предоставляет глобальный контекст как средство доступа и хранения всех состояний. Глобальный контекст предоставляет все нужные данные о текущем событии в приложение, а также механизм хранения и общего использования информации компонентами приложения.
Глобальный контекст разделен на ряд зон, каждая из которых хранит данные с различной видимостью и различным циклом жизни, как показано на рисунке 2. Например, зона user содержит состояние сеанса для данного клиента, видима только этому клиенту и хранит данные до тех пор, пока клиент активен.
Зона request содержит состояние текущего активного запроса, видима только компонентам, выполняющимся для этого запроса, и хранит состояние только до конца этого запроса.
Рисунок 2. Глобальный контекст
Соглашения и структура каталога приложения
Среда Zero предлагает несколько соглашений, следование которым значительно упрощает разработку Zero-приложений и минимизирует конфигурационную информацию, которую нужно указать. Целью Zero является минимизация конфигурационной информации. Некоторые соглашения обычны и ожидаемы. Например, вы можете поместить сценарий в общедоступную папку вашего приложения и выполнять этот сценарий в ответ на HTTP-запрос без конфигурационных данных.
Другие соглашения более приспособлены к конкретному шаблону. На рисунке 3 показан пример хранения Groovy-сценария в отдельной папке. При таком подходе автоматически регистрируются методы в этой папке в ответ на HTTP REST-события. Позднее в данной статье вы узнаете, как используется RESTful-шаблон быстрой разработки RESTful-сервисов для отображения ваших данных. Дополнительная информация приведена в разделе Virtual Directory "Руководства разработчика Project Zero".
Рисунок 3. Виртуализированные каталоги
Мы почти готовы к созданию первого RESTful-сервиса с использованием платформы Zero. Давайте сначала рассмотрим концепции, используя следующий пример.
В этой сери статей мы создадим пример для изучения различных концепций. Тема примера - стимулирование скидками. Потребители всегда ищут стимулы (incentive), а поставщики должны их предоставить. На диаграмме варианта использования (рисунок 4) показаны различные действия. В данной статье мы сконцентрируемся на роли поставщика и варианте использования "управление стимулами".
Рисунок 4. Вариант использования
Поставщик нуждается в способе ввода и управления стимулами в системе; стимул - это основная часть данных, которая нас интересует. На рисунке 5 показана модель данных для приложения incentive.
Рисунок 5. Модель данных
Мы начнем с таблицы. В следующих статьях мы расширим модель данных и добавим взаимосвязи, рассмотрим более сложные данные, используя REST-парадигму.
Проектирование оконечных точек RESTful
После создания набора данных мы отобразим эти данные в RESTful-пространство имен. Обычно очень полезно создать таблицу для конкретного логического объекта с целью отображения ресурса. В таблице 1 показан пример RESTful-отображения на наш ресурс. Мы и будем создавать этот RESTful-сервис.
Таблица 1. REST-данные
| Ресурс | URI | Метод | Представление | Описание |
| Incentive list | /incentive | GET | JSON-массив объектов | Извлечь список стимулов |
| Incentive | /incentive | POST | JSON-объект | Создать новый стимул |
| Incentive | /incentive/<incentiveId> | GET | JSON-объект | Извлечь конкретный стимул |
| Incentive | /incentive/<incentiveId> | PUT | JSON-объект | Обновить отдельный стимул |
| Incentive | /incentive/<incentiveId> | DELETE | Удалить отдельный стимул |
Для представления данных выбран формат JSON, поскольку мы будем использовать RIA-приложение (Rich Internet Application - полнофункциональное интернет-приложение) в качестве интерфейса системы. Большинство инструментальных средств для работы с Ajax очень хорошо понимают JSON, поскольку основным языком программирования Ajax в браузере является JavaScript (ссылки на более подробную информацию о JSON приведены в разделе "Ресурсы").
Для запуска примеров данной статьи необходимы:
- Eclipse 3.2 или выше. Мы использовали версию Eclipse 3.3.
- Project Zero Java and Groovy Plug-in for Eclipse.
Этот пример был создан с использованием Zero версии M1 Release. Установите Eclipse Update Site в значение http://www.projectzero.org/update/zero.eclipse.M1.
В данном упражнении нам не понадобится PHP Plug-in.
- К данной статье прикреплен загружаемый zip-файл. Разархивируйте его на диск C:.
- Derby Network Database.
- Derby Plug-in for Eclipse.
-
Браузер Firefox.
Хотя в данном упражнении можно использовать IE, мы применяем плагин Firefox для тестирования запросов POST/PUT/DELETE. При использовании IE вы можете тестировать GET-запросы в браузере, а затем протестировать сервисы, используя UI-клиент, который мы импортируем позже.
- Плагин POSTER для Firefox.
Другие полезные инструментальные программы:
- Aptana Eclipse Plug-in для инструментальных средств HTML/JavaScript.
- Eclipse Europa.
- FireBug.
Создание первого RESTful-сервиса при помощи Project Zero
Теперь, когда мы немного узнали о RESTful-отображении, пора создать пример.
- Сначала мы создадим Zero-проект.
- В основном меню Eclipse выберите New > Project, как показано на рисунке 6.
Рисунок 6. Создание нового проекта
- В мастере Project Wizard выберите Zero > Project Zero Application. Нажмите кнопку Next, как показано на рисунке 7.
Рисунок 7. Project Zero Application
- Назовите проект
RebateIncentiveServicesи нажмите кнопку Finish.
Рисунок 8. RebateIncentiveServices
- На следующем шаге мы исследуем структуру каталога Project Zero и инструментарий.
- На рисунке 9 показано несколько важных каталогов в Zero-проекте. Выделенные папки - это различные области, которые можно кодировать. Основная часть этих каталогов расположена в папке app проекта. В окне Project Explorer перспективы Java эти каталоги выглядят как папки Java source.
Рисунок 9. Структура каталогов приложения
- Java
- В папке Java можно предоставить Java-код, который будет использоваться в приложении. Можно написать Java-обработчики и поместить их сюда.
- Public
- В папке public размещаются все артефакты, которые вы хотите предоставлять для браузера. Например, HTML-файлы, JavaScript-файлы, Groovy-файлы и шаблоны, которые могут выполняться в браузере, либо PHP-сценарии.
- Resources
- Папка /app/resources содержит сценарии (Groovy или PHP), которые будут активизироваться в ответ на RESTful-вызовы. Они соответствуют различным HTTP-методам. Сценарии в этом каталоге автоматически регистрируются как обработчики. В примере мы будем использовать этот каталог.
- Errors
- Папка /app/errors будет содержать файлы шаблонов, например, Groovy-шаблоны, которые будут визуализироваться автоматически в зависимости от ошибок. Схема наименования файлов определяет, какой ресурс визуализируется. Например, error5xx.gt - это Groovy-шаблон, который будет активизироваться в ответ на ошибку сервера 500.
- Scripts
- Каталог /app/scripts позволяет определить Groovy-сценарии или классы, являющиеся приватными по природе (аналогично каталогу Java). Здесь можно определить компоненты GroovyBeans или методы, которые можно активизировать в Groovy-сценариях public или resources. Такой подход позволяет придерживаться шаблона модель-представление-контроллер (Model-View-Controller - MVC) при создании приложения.
- Views
- В каталоге /app/views помещаются файлы шаблонов, которые могут активизироваться в ответ на определенное событие. В отличие от сценариев в каталоге public (запускающихся на основе прямого URL-доступа) эти представления могут выполняться из другого сценария. Сценарий контроллера может обратиться к определенной серверной логике, а затем передать управление сценариям views для визуализации.
Более подробная информация о структуре каталогов приложения приведена в "Руководстве разработчика Project Zero" (см. раздел "Ресурсы").
- На рисунке 10 выделен каталог Config, который содержит важные файлы, необходимые для нашего Zero-приложения.
Рисунок 10. Каталог Config
- Ivy.xml
- Платформа Zero использует интегрированную среду Ivy для обслуживания зависимостей. Zero-приложения упакованы в пакеты (packages). Наш ivy.xml позволяет определить зависимые пакеты. Zero-пакеты хранятся в репозитории Ivy. Они разрешаются системой времени исполнения Ivy.
Ivy - это инструментальная программа для управления (запись, отслеживание, разрешение и создание отчетов) зависимостями проекта. Ее характеристики:
- Гибкость и настраиваемость.
Ivy, по существу, не зависит от процесса и не связана с какой-нибудь методологией или структурой. Она обеспечивает необходимую гибкость и настраиваемость для адаптации к широкому диапазону процессов компоновки и управления зависимостями.
- Тесная интеграция с Apache Ant.
Хотя Ivy доступна как автономная инструментальная программа, особенно хорошо она работает с Apache Ant, обеспечивая несколько мощных Ant-заданий, например, разрешение зависимостей и составление отчетов о зависимостях и их публикация.
Дополнительная информация об Ivy приведена в Apache-инкубатор (EN) или в разделе Dependency and Packaging "Руководства разработчика Project Zero".
- Гибкость и настраиваемость.
- logging.properties
- В файле logging.properties можно настраивать параметры ведения журналов регистрации событий Java. Zero использует систему Java Development Kit (JDK) для регистрации событий (дополнительная информация о регистрации событий в Zero приведена в разделе Logging "Руководства разработчика Project Zero").
- Zero.config
- Файл zero.config является основным конфигурационным файлом Zero-приложения. В нем настраиваются такие артефакты как обработчики, система защиты, источники данных и вся другая необходимая конфигурация. Можно иметь несколько файлов zero.config. Мы определим некоторые конфигурационные параметры базы данных в примере, используя zero.config. Поскольку пример будет использовать папку /app/resources, нам не нужно явно конфигурировать обработчики; мы будем полагаться на предопределенные в Zero обработчики для REST-вызовов (более подробная информация о конфигурировании приведена в разделе Configuration "Руководство разработчика Project Zero").
На рисунке 11 выделены аспекты инструментария Eclipse. Плагин Zero обеспечивает средства, помогающие управлять зависимостями. Он позволяет управлять локальным и удаленными репозиториями, которые интегрированная среда Ivy может использовать для загрузки и разрешения зависимостей Zero-приложения. Разрешение зависимости означает добавление пакета в Zero-приложение.
Рисунок 11. Управление зависимостями
- Управление репозиториями
- Предоставляет инструментальное средство для просмотра локального репозитория и загрузки пакетов из удаленных репозиториев, как показано на рисунке 12.
Рисунок 12. Управление репозиториями
- Пиктограмма resolve
- Пиктограмма resolve разрешает зависимости в рабочей области из локального и удаленного репозиториев.
- Элемент меню resolve
- Элемент меню resolve разрешает зависимости из локальных репозиториев.
- Для создания нашего RESTful-сервиса необходимо создать таблицу в базе данных. Для примера предоставлен сценарий настройки базы данных. В упражнении используется сетевая версия Derby (мы также установили плагин Derby для Eclipse).
- Щелкните правой кнопкой мыши на RebateIncentiveServices и выберите Import, как показано на рисунке 13.
Рисунок 13. Импорт артефактов
-
Рисунок 14. Файловая система
- Если предположить, что вы разархивировали загружаемый zip-файл примера на диск C, в поле From directory следует использовать значение C:\ProjectZeroArticleSeries\Part1. В поле Into folder должно быть указано RebateIncentiveServices. Выберите папку dbscripts, как показано на рисунке 15, и нажмите кнопку Finish.
Рисунок 15. DB-сценарии
- Вы должны увидеть в проекте папку под названием dbscripts. В этой папке откройте Incentives.sql. Данный сценарий создает таблицу incentive и вставляет в нее две записи.
Рисунок 16. Incentives.sql
Исходный код сценария показан в листинге 1.
Листинг 1. Сценарии базы данныхCONNECT 'jdbc:derby://localhost:1527/INCENTIVEDB;create=true;'; drop table Incentive; create table Incentive ( incentiveid INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, name VARCHAR(256) NOT NULL, description VARCHAR(256) NOT NULL, providername VARCHAR(50) NOT NULL, incentivetype VARCHAR(128), validfrom TIMESTAMP, validto TIMESTAMP, website VARCHAR(256) ); alter table Incentive ADD CONSTRAINT Incentive_PK PRIMARY KEY (incentiveid); INSERT INTO Incentive (name,description,providername,incentivetype,validfrom,validto,website) values ('Key Account Energy Efficiency Grant Program', 'Alameda P&T offers its commercial customers grants of up to $25,000 for energy efficient building design and equipment in new commercial construction, or other approved unique energy efficient projects.', 'Alameda Power and Telecom','Energy', TIMESTAMP('2007-06-22 00:00:00.000'), TIMESTAMP('2007-10-30 00:00:00.000'), 'http://www.alamedapt.com/electricity/com_savings.html' ); INSERT INTO Incentive (name,description, providername,incentivetype,validfrom,validto,website) values ( 'Power Management for Personal Computer (PC) Networks', 'Avista Utilities Power Management for Personal Computer (PC) Networks offers incentives to commercial customers.', 'Avista Utilities','Energy', TIMESTAMP('2007-09-01 00:00:00.000'), TIMESTAMP('2008-06-30 00:00:00.000'), 'http://www.avistautilities.com/saving/conservation/power_management.asp' );
- Если у вас установлен Apache Derby Plug-in for Eclipse, щелкните правой кнопкой мыши на проекте, как показано на рисунке 17, и выберите Apache > Add Apache Derby
nature.
В качестве альтернативного способа запуска Derby используйте командную строку и вручную запустите
ij.
Рисунок 17. Apache Derby Plug-in
- Снова щелкните правой кнопкой мыши на проекте и выберите Apache Derby > Start Derby Network Server, как показано на рисунке 18.
Рисунок 18. Сервер Start Derby network
- Проверьте в консоли, работает ли база данных.
Рисунок 19. Выполнение базы данных Derby
- Щелкните правой кнопкой мыши на сценарии Incentive.sql и выберите Apache Derby > Run sql script running 'ij' (это программа командной строки для выполнения сценариев базы данных Derby).
Рисунок 20. Выполнение SQL-сценариев с использованием ij
- Проверьте в консоли, что таблица создана и записи вставлены.
Рисунок 21. Результаты работы сценария базы данных
- Ранее мы рассматривали файл ivy.xml. При создании Zero-проекта мы получили пакет ядра Zero и пакет Webtools. Ядро содержит необходимые библиотеки для создания обработчиков событий и RESTful-сервисов, а также для взаимодействия с глобальным контекстом и системой защиты. Проект Web Tools содержит набор полезных инструментальных средств, например, индексную страницу по умолчанию, инспектор запросов, инструменты поиска ошибок и т.д. Дополнительная информация приведена в разделе Developer Web tools "Руководства разработчика Project Zero" (см. раздел "Ресурсы").
На следующем шаге мы добавим в приложение два пакета. Для работы с базой данных необходимы библиотеки доступа к данным, а также JAR-файлы Derby-клиента.
- Откройте файл ivy.xml, как показано на рисунке 22.
Рисунок 22. ivy.xml
- При этом открывается редактор ivy.xml. Нажмите кнопку Add, как показано на рисунке 23.
Рисунок 23. Добавление пакетов Zero
- Найдите пакет zero:zero.data, как показано на рисунке 24. Установите filter в значение Latest minor version и нажмите кнопку OK.
Рисунок 24. Пакет zero.data
- Повторите предыдущий шаг и добавьте org.apache.derby:derbyclient. При этом добавляются JAR-файлы JDBC-клиента (Java Database Connectivity), необходимые для подключения к Derby.
Рисунок 25. Derby-клиент
- Выберите пиктограмму Update dependencies. Программа читает файл ivy.xml и ищет последнюю версию локального и удаленных репозиториев (позже в нашем примере мы будем использовать параметр Resolve).
Рисунок 26. Обновление зависимостей
- Нажмите кнопку OK, чтобы позволить программе проверить наличие удаленных версий.
Рисунок 27. Выбор запускаемых зависимостей
- Теперь, когда приложение имеет необходимые библиотеки, необходимо настроить базу данных во время исполнения. Файл zero.config использует INI-стиль конфигурирования. Содержимое файла config/zero.config организовано по "строфам" ("stanzas") связных пар ключ/значение.
Строфы ассоциируются с директивами, например, "store to the global context" (сохранить в глобальном контексте) и "include another configuration file" (включить еще один конфигурационный файл). Хотя целью Project Zero является минимизация количества конфигурационных параметров, необходимых для запуска приложения, определенная настройка все же необходима.
- Разверните папку Config и откройте файл zero.config, как показано на рисунке 28.
Рисунок 28. zero.config
- На рисунке 29 показана добавляемая строфа.
Рисунок 29. Конфигурирование базы данных
Обратите внимание на то, что строфа начинается с директивы. В данном случае мы указываем месторасположение, куда решили сохранять пары ключ/значение. Тест показан в листинге 2. Вы можете также скопировать его из файла C:\ProjectZeroArticleSeries\Part1\dbconfig.txt.
Листинг 2. Конфигурация базы данных[/app/db/incentiveDB/config] class=org.apache.derby.jdbc.ClientDataSource serverName=localhost portNumber=1527 databaseName=INCENTIVEDB connectionAttributes=create=true
Библиотеки данных Project Zero будут читать эту конфигурацию во время обращения к базе данных. Обратите внимание на выделенное на рисунке 29 имя incentiveDB после /app/db. Это имя, которое будет использоваться в коде. Мы увидим это при компоновке RESTful-сервисов.
Создание RESTful-сервиса для представления данных
Пора скомпоновать RESTful-сервис для представления данных о стимулах. В Project Zero имеется несколько способов создания сервисов. Нашей целью является использование преимуществ встроенной поддержки для автоматического отображения Groovy-сценариев в виде RESTful-сервиса.
Мы будем использовать плагин Eclipse для Project Zero. Помните о том, что эти же соглашения доступны также и вне Eclipse - в версии Zero командной строки. Вы увидите, насколько быстро можно создать REST-сервисы, используя Project Zero.
Groovy-сценарий будет соответствовать имени URL, по которому мы хотим активизировать REST-сервис. Для /resources/incentive нам необходим файл под названием incentive.groovy.
- Щелкните правой кнопкой мыши на папке /app/resources и выберите New > File, как показано ниже.
Рисунок 30. Новый файл
- Назовите файл
incentive.groovy.
Рисунок 31. incentive.groovy
- Нажмите кнопку Yes при запросе добавления в проект поддержки Groovy.
Рисунок 32. Поддержка Groovy t
Для управления стимулами мы хотим предоставить возможность выводить список всех стимулов, выводить конкретные стимулы и создавать, обновлять и удалять стимулы. Первой задачей является предоставление возможности выводить список стимулов. Клиенты могут вызвать /resources/incentive для просмотра этого списка.
- Откройте только что созданный файл incentive.groovy.
Рисунок 33. Incentive.groovy
- Если вы введете код сценария напрямую, то создадите сценарий, отвечающий на все HTTP-методы. Однако нам нужны разные действия для разных HTTP-методов. Можно определить специализированные методы обработчиков, которые автоматически отвечают на HTTP-метод. В приведенной ниже таблице перечислены эти методы обратного вызова (callbacks).
URI HTTP-метод Groovy-метод Описание /incentive GET onList() Возвращает список стимулов /incentive POST onCreate() Создает новый стимул и возвращает месторасположение ресурса /incentive PUT onPutCollection() Обновляет набор стимулов /incentive DELETE onDeleteCollection() Удаляет набор стимулов /incentive/<incentiveId> GET onRetrieve() Извлекает стимул по ID /incentive/<incentiveId> PUT onUpdate() Обновляет конкретный стимул /incentive/<incentiveId> DELETE onDelete() Удаляет конкретный стимул /incentive/<incentiveId> POST onPostMember() Передает конкретный член в выбранное вами месторасположение
В данной статье мы создадим методы обратного вызова 1, 2, 5, 6 и 7.
- Для создания и тестирования списка добавьте фрагмент кода, приведенный в листинге 3. Можно также скопировать его из файла C:\ProjectZeroArticleSeries\Part1\list.txt.
Листинг 3. Список стимуловimport zero.data.groovy.Manager; def onList() { def dm = Manager.create("incentiveDB"); request.json.output = dm.queryList("select * from incentive"); request.view="JSON"; render(); }
Этот код:
- Использует объект
Managerиз data API Project Zero. ОбъектManagerпредоставляет удобные методы для выполнения SQL-запросов. Имеется две версии: Java-версия и Groovy-версия. Java-версия работает в Groovy, а Groovy-версия использует преимущества сокращенных команд Groovy, например, передачи GStrings как входных параметров, использование замыканий (closures) и т.д. При вызовеcreateмы передаем строку, используемую в конфигурационном файле /app/db/incentiveDB/config. - Выбирает полный список из
Managerи назначает его в request.json.output. Это может выглядеть так, как будто мы назначаем результаты обычной переменной Groovy, но на самом деле происходит нечто большее. Помните, что все состояния хранятся в глобальном контексте. Project Zero предоставляет Java API для сохранения и извлечения данных изGlobalContext.Например, код
String data = GlobalContext.get("/request/myData");
получает строку из раздела request глобального контекста. Далее groovy-сценарии Project Zero добавляют встроенную поддержку данных глобального контекста. Они предопределили четыре переменные для каждого раздела (app, user, request и event). То есть, в Groovy исходный код:request.myData = "Hello"
аналогиченGlobalContext.put("/request/myData","Hello);
Использование преимуществ таких сокращений в Groovy уменьшает объем кода, который нужно написать. В данном примере мы сохраняем список в разделе request в каталоге /request/json/output. Дополнительная информация о глобальном контексте приведена в "Руководстве разработчика Project Zero" (см. раздел "Ресурсы").
После сохранения результатов в
GlobalContextиспользуется еще один объект под названиемViewEngine. Project Zero поддерживает различные способы визуализации полученного контекста. Можно явно записать все в выходной поток (прямая визуализация). Код приложения и обработчики событий могут записать данные напрямую в логический объектresponse, используя объектыOutputStream(/request/outputstream) иPrintWriter(/request/writer).Вот пример на Java:
// Содержимое Java-класса PrintWriter writer = (PrintWriter) GlobalContext.get("/request/writer"); writer.println("Hello World.");
Выходным потоком по умолчанию для всех Groove-сценариев (включая шаблоны) является response writer, позволяющий разработчикам приложений писать напрямую в ответ при помощи метода
println. Подробная информация по визуализации приведена в разделе Rendering Results "Руководства разработчика Project Zero".Project Zero предоставляет библиотеку визуализаторов для обычной обработки ответа. Активизация визуализатора обычно включает в себя следующие шаги:
- Настроить значение
/request/viewв глобальном контексте на соответствующий визуализатор. - Установить дополнительные специфичные для визуализатора значения в
GlobalContext. - Аактивизировать
zero.core.views.ViewEngine.render()
В Groovy REST Handler вызовrender()приведет к вызову визуализатора View Engine.
zero.coreсодержит визуализаторы View, Error, XML и JSON. Можно также добавить пакет Atom, который содержит визуализатор Atom.В примере используется JSON-обработчик. Еще одной альтернативой является использование Groovy-шаблона. Groovy-шаблон можно сохранить в папке /app/views и установить request.view в имя этого шаблона.
Как можно заметить, эти соглашения значительно уменьшают количество кода, который требуется написать.
- Использует объект
Тестирование путем запуска приложения
Теперь можно легко протестировать onList путем запуска приложения.
- Щелкните правой кнопкой мыши на проекте и выберите Run as > Project Zero Application, как показано на рисунке 34.
Рисунок 34. Запуск приложения Project Zero
- Проверьте консоль. Приложение должно запуститься и прослушивать порт 8080.
Рисунок 35. Приложение, работающее на порту 8080
- Запустите браузер и перейдите по адресу http://localhost:8080. При этом должна отобразиться zero-страница по умолчанию (это одна из инструментальных программ в библиотеке Web Tools, о которой упоминалось выше). Вы увидите индексную страницу по умолчанию. Если добавить свой собственный файл index.html, он будет иметь приоритет над файлом по умолчанию.
Рисунок 36. Домашняя страница по умолчанию
- Запустите программу Firefox Poster, выбрав View > SideBar > Poster.
Рисунок 37. Запуск плагина Poster
- Введите
http://localhost:8080resources/incentiveв качестве URL и нажмите GET.
Рисунок 38. Результат GET incentives
- Должно отобразиться окно Response, показанное ниже. Используется формат JSON-массива, каждый элемент которого представлен как JSON-объект.
Рисунок 39. JSON-результат
- Можно также при желании протестировать XML-визуализацию. Измените тип представления на XML, как показано в листинге 4.
Листинг 4. XML-результатdef onList() { def dm = Manager.create("incentiveDB"); request.xml.output = dm.queryList("select * from incentive"); request.view="XML"; render(); }
- Снова нажмите GET в плагине Poster для просмотра результатов в XML, показанных на рисунке 40.
Рисунок 40. XML-результаты
Не забудьте изменить код обратно на JSON.
Далее мы создадим метод onRetrieve для доступа к специализированному RESTful-сервису, указанному путем передачи его идентификатора.
- В файле incentive.groovy добавьте метод
onRetrieveи исходный код, показанный на рисунке 41 или в листинге 5 ниже. В качестве альтернативного способа можно скопировать код из файла C:\ProjectZeroArticleSeries\Part1\retrieve.txt.
Рисунок 41. Извлечение стимула
Листинг 5. Извлечение одного стимулаdef onRetrieve() { def dm = Manager.create("incentiveDB"); request.json.output = dm.queryFirst( "select * from incentive where incentiveid = ${request.params.incentiveId[0].get()}"); request.view="JSON"; render(); }
Аналогично методу
onListмы создадим экземплярManagerи выполним запрос. К данному примеру нужно сделать несколько важных замечаний:- Метод будет выполняться по следующему URI: /resources/incentive/1. 1 - это идентификатор желаемого стимула. Для передачи его в выражение
whereнеобходимо обратиться к URI. Zero автоматически заполняетGlobalContextинформацией о пути. Например,request.params.incentiveId[0]возвратит 1. В таблице ниже приведено несколько примеров того, как можно обратиться к параметрам.URI Параметры /incentive/1 request.params.incentiveId[0] == 1 /incentive/1/provider?location=NJ request.params.location[0] == NJ
- В запросе используется встроенная поддержка Groovy GStrings. GString позволяет использовать язык выражений для обращения к переменным в строковом литерале. Поэтому, следующий строковый литерал запроса:
select * from incentive where incentiveid = ${request.params.incentiveId[0].get()}
cможет получить прямой доступ кGlobalContext. В качестве альтернативного способа можно использовать API в библиотеках доступа к данным, позволяющим передавать POJO-объекты (Plain Old Java Objects) и использовать:property-стиль ввода, а также поддержку параметров типа?. Дополнительная информация приведена в разделе JavaDocs (EN) для Project Zero и Data Access в "Руководстве разработчика Project Zero" (см. раздел "Ресурсы").
- Метод будет выполняться по следующему URI: /resources/incentive/1. 1 - это идентификатор желаемого стимула. Для передачи его в выражение
- Сохраните файл. Вернитесь в программу Firefox Poster, введите URL
http://localhost:8080/resources/incentive/1и нажмите кнопкуGET, как показано на рисунке 42. Результатом должен быть JSON-объект с одной записью.
Рисунок 42. JSON-результат для одного стимула
А сейчас добавим методы onCreate(), onUpdate() и onDelete().
- Введите исходный код, приведенный в листинге 6, в incentive.groovy, либо скопируйте его из файла C:\ProjectZeroArticleSeries\Part1\updateMethods.txt.
Листинг 6. Создание, обновление и удаление стимулаdef onCreate() { def dm = Manager.create("incentiveDB"); def incentive = zero.json.JsonType.fromData(request.input.get()).getJson(); def newKey = dm.insert("insert into incentive (name,description,providername,incentivetype,validfrom,validto,website) values(${incentive.name},${incentive.description},${incentive.providername}, ${incentive.incentivetype},${incentive.validfrom},${incentive.validto}, ${incentive.website})",['incentiveid']); locationUri = zero.core.utils.URIUtils.getAbsoluteUri(request.path) + '/' + newKey request.headers.out.Location = locationUri request.status = HttpURLConnection.HTTP_NO_CONTENT } def onUpdate() { def dm = Manager.create("incentiveDB"); def incentive = zero.json.JsonType.fromData(request.input.get()).getJson(); dm.update("update incentive set name = ${incentive.name},description = $incentive.description ,providername = $incentive.providername,incentivetype=$incentive.incentivetype,validfrom= $incentive.validfrom,validto=$incentive.validto, website=$incentive.website where incentiveid=${request.params.incentiveId[0].get()}"); request.status = HttpURLConnection.HTTP_NO_CONTENT } def onDelete() { def dm = Manager.create("incentiveDB"); def newKey = dm.update("delete from incentive where incentiveid= ${request.params.incentiveId[0].get()}"); request.status = HttpURLConnection.HTTP_NO_CONTENT; }
В этом коде:- API доступа к данным имеют методы для выполнения обновлений.
onDeleteиonUpdateиспользуют общий методupdate, позволяющий передавать любое выражениеInsert,UpdateиDeleteбазы данных.onCreate()также использует специально определенный метод insert, возвращающий первичный ключ. - Метод
onCreateустанавливает URL нового созданного ресурса. Это предусматривается REST-шаблоном. - Все обновления устанавливают возвращаемый тип в
no Content. - Использование специализированного
zero.json.JsonType.fromDataпреобразует тело сообщения в Java-представление JSON-объекта.
- API доступа к данным имеют методы для выполнения обновлений.
- Используя Poster, введите
http://localhost:8080/resources/incentive. В Content to Send добавьте JSON-объект из листинга 7 (или скопируйте его из файла C:\ProjectZeroArticleSeries\Part1\insertUpdatePayload.txt).
Листинг 7. Создание JSON-нагрузки{"providername":"Hawaii Gas Company ", "website":"http://www.hawaiigas.com/rebate/commercial.html", "description":"Existing Commercial Utility Gas customers of The Gas Company may apply for a rebate for new gas equipment..", "name":"Commercial Switch to Gas Program", "incentivetype":"Energy","validto":"2007-09-01 13:01:23.123456", "validfrom":"2008-06-30 13:01:23.123456"}
- Выберите POST, как показано на рисунке 43.
Рисунок 43. POST incentive
- Ответом должен быть код 204, а месторасположение должно быть установлено в новый ресурс http://localhost:8080/resources/incentive/3, как показано на рисунке 44.
Рисунок 44. Результат POST
- Закройте ответ и вернитесь к программе Poster. Введите новый URL
http://localhost:8080/resources/incentive/3и нажмите кнопку GET для проверки создания записи.
Рисунок 45. GET для созданного стимула
- Вы должны получить ответ, совпадающий с созданной вами записью.
Рисунок 46. GET для нового стимула
- Снова скопируйте рабочую нагрузку из файла C:\ProjectZeroArticleSeries\Part1\insertUpdatePayload.txt.
- Измените тип
incentiveTypeнаGas, как показано в JSON-объекте в листинге 8.
Листинг 8. Обновление JSON-нагрузки{"providername":"Hawaii Gas Company ", "website":"http:\/\/www.hawaiigas.com\/rebate\/commercial.html", "description":"Existing Commercial Utility Gas customers of The Gas Company may apply for a rebate for new gas equipment..", "name":"Commercial Switch to Gas Program", "incentivetype":"Gas", "validto":"2007-09-01 13:01:23.123456", "validfrom":"2007-09-01 13:01:23.123456"}
- Введите URL ресурса
http://localhost:8080/resources/incentive/3и нажмите кнопку PUT.
Рисунок 47. PUT для стимула
- Вы должны получить ответ 204.
Рисунок 48. Результат 204
- Выполните еще один GET с ресурсом для проверки успешности обновления.
Рисунок 49. Удаление стимула
- Наконец, в URL http://localhost:8080/resources/incentive/3 нажмите кнопку Delete. Вы должны получить ответ 204, как показано ниже.
Рисунок 50. Ответ 204 для операции удаления
- Выполните запрос GET. Вы должны получить пустой результат (в следующих статьях данной серии мы добавим в исходный код обработку ошибок).
Теперь, после проверки функционирования RESTful-сервисов, перейдем к импорту примера RIA-приложения, которое будет потреблять RESTful-сервисы. В данной статье клиентскому приложению не уделяется много внимания, а лишь просто кратко рассматривается импортируемый клиент и объясняется, почему REST является одной из основ mashup-приложений.
В настоящее время Project Zero содержит Dojo Toolkit 4.3. В качестве примера мы будем использовать Dojo-приложение. Мы будем использовать базовую поддержку Dojo с некоторыми импортированными вспомогательными модулями.
Для добавления Dojo-пакета в проект:
- Так же, как и прежде, откройте ivy.xml в папке Config и добавьте dojo:dojo(0.4.3) в ваше приложение.
Рисунок 51. Добавление Dojo-пакета
- Щелкните правой кнопкой мыши на проекте и выберите Zero Tools Resolve. При этом разрешится Dojo из локального репозитория.
Можете также использовать пиктограмму Update Dependencies для загрузки из удаленного репозитория, как делали это раньше.
Рисунок 52. Разрешение Dojo
- Остановите приложение в консоли, нажав Stop, как показано на рисунке 53. В отличие от изменений в коде, при добавлении новых библиотек или обновлении zero.config необходимо перезапустить приложения.
Рисунок 53. Остановка приложения
Теперь можно выполнить импорт и исследовать исходный код:
-
Щелкните правой кнопкой мыши на папке public проекта и выберите Import.
Рисунок 54. Импорт UI-кода
- В поле From directory введите
C:\ProjectZeroArticleSeries\Part1\webapp. Отметьте флажок webApp и убедитесь, что папка Into folder установлена в public, как показано на рисунке 55.
Рисунок 55. Мастер Import Wizard
Давайте вкратце рассмотрим исходный код:
- Откройте index.html, как показано на рисунке 56.
Рисунок 56. Файл index
- Мы создали клиентское приложение в виде виджета (widget). Создание RESTful-клиентов в виде Dojo-виджетов является основой реализации модульных клиентских приложений, которые можно интегрировать в mashup-приложения. На рисунке 57 показано, что виджет incentive является единственным объявлением на странице.
В примере есть еще один добавленный фрагмент JavaScript-кода для симуляции второго виджета. Этот виджет будет подписываться на виджет incentive и отображать RESTful-события.
Рисунок 57. Два виджета
- В папке zero.incentive.widget вы найдете исходный код, необходимый для создания Dojo-виджета. Dojo-виджет состоит главным образом из HTML-шаблона, CSS-файла для стилевого оформления и JavaScript-функции. Создание Dojo-виджета является темой отдельной статьи. Ссылки на информацию по Dojo Toolkit и виджетам приведены в разделе "Ресурсы". На рисунке 58 выделены файлы виджета.
Рисунок 58. Исходный код Dojo-виджета
- В листинге 9 выделен фрагмент файла IncentiveWidget.js, в котором показан способ активизации Dojo-виджетом нашего RESTful-сервиса. Предоставляется пример JavaScript-класса
JSONRestService, который мы вкратце рассмотрим. В примере показано, как виджет активизирует методlistDataдля активизации сервиса. Еще одним важным аспектом является использование Dojo-функций publish и subscribe для генерирования событий об активизации RESTful-сервисов. Таким образом, соседние виджеты узнают о том, когда произошел доступ к данным.Помните о том, что некоторые данные могут быть защищенными. JavaScript mashup-приложения из непроверенных источников могут быть очень опасными. В следующей статье данной серии мы рассмотрим более безопасные шаблоны.
Листинг 9. Вызов JSON restpostCreate: function(){ dojo.debug("postCreate, setting subscriptions"); //Загрузить Widget dojo.event.topic.subscribe(this.inputTopic, this, this.listIncentives); //Получить события Incentives dojo.event.topic.subscribe(this.getAllTopic, this, this.bindIncentives); listIncentives:function (){ zero.rest.JsonRestService.listData(this.restUri, this.getAllTopic,this.errorListTopic); }, bindIncentives:function(data){ dojo.debug("Binding to -> " + this.incentiveTable); for(i = 0; i < data.length ; i++) { data[i].validto = dojo.date.fromIso8601 (data[i].validto); data[i].validfrom = dojo.date.fromIso8601 (data[i].validfrom); data[i].website = '<a href=\"' + data[i].website + '\" target="_blank">' + data[i].website + '</a>'; } this.incentiveTable.store.setData(data); this.showIncentiveFormButton.show(); this.editIncentiveFormButton.show(); this.deleteIncentiveButton.show(); }
- Откройте файл JsonRestService.js в папке zero.rest, как показано на рисунке 59. В исходном коде обратите внимание на метод
callbackдля всех RESTful-событий. Мы используем методdojo.io.bind()и dojo publish/subscribe для уведомления о совершении событий. Этот код также можно увидеть в "Руководстве разработчика" (EN).
Рисунок 59. JsonRestService.js
Теперь запустите клиентское приложение:
- Перезапустите приложение. Это можно сделать, используя стрелку Eclipse run, как показано ниже.
Рисунок 60. Перезапуск приложения
- Укажите в браузере http://localhost:8080. Обратите внимание на то, что вместо индексной страницы Web Tools активизируется наша индексная страница. Виджет incentive вызывает список данных, а соседний виджет отображает событие.
Рисунок 61. Загруженное приложение
- Добавьте новый стимул, нажав кнопку Add New Incentive.
Рисунок 62. Добавление нового стимула
- Введите некоторые данные (можно использовать JSON-нагрузку в качестве примера или посмотреть на рисунок 63).
Рисунок 63. Добавление новой формы incentive
- Нажмите кнопку Submit. В таблицу должен добавиться созданный только что ресурс.
Рисунок 64. Обновление стимула
- Выделите только что созданный ресурс и нажмите Edit Selected Incentive.
При выборе ресурса выполняется метод
onRetrieveс целью получения конкретного ресурса. - Обновите любое поле и нажмите кнопку Submit.
В Dojo версии 4.3 имеется маленькая ошибка в виджете даты, отображающей данные формы. Проверьте наличие обновлений на сайте Dojo либо заполните виджет напрямую.
Рисунок 65. Ошибка в Dojo 4.3
- Наконец, выделите ресурс и нажмите Delete Selected Incentive.
Рисунок 66. Удаление стимула
- Список должен обновиться, как показано на рисунке 67.
Рисунок 67. После удаления стимула
- Проверьте виджет neighbour, который должен отображать REST-событие и данные.
Рисунок 68. Мастер mashed-up
Поздравляем с созданием вашего первого RESTful-сервиса при помощи Project Zero!
В данной статье вы познакомились с Project Zero - новой платформой для создания Web-приложений или расширенной на Web архитектуры SOA. Вы узнали об архитектуре Project Zero и о том, как создать RESTful-сервисы, используя возможности Web 2.0 разработки. Наш относительно простой пример использовал распространенный шаблон.
Не пропустите вторую часть, в которой мы рассмотрим создание RESTful-сервисов для более сложных данных и представим другие части платформы, которые помогут в компоновке, защите и реализации полнофункциональной, расширенной на Web архитектуры SOA.
| Описание | Имя | Размер | Метод загрузки |
|---|---|---|---|
| Пример кода | i-zero1code.zip | 13 КБ | HTTP |
Научиться
- Оригинал статьи "Introducing Project Zero, Part 1: Building RESTful services for your Web application" (EN).
- Узнайте все о Project Zero - простой среде, предназначенной для создания, компоновки и выполнения приложений, основанных на популярных Web-технологиях (EN).
- "Руководство разработчика Project Zero" - информация о базовых концепциях, определяющих архитектуру Zero-приложения (EN).
- Используйте форум Project Zero Forum, чтобы получить помощь, ответы на вопросы, информацию, обсуждения предстоящих разработок и многое другое (EN).
- Узнайте о Groovy - динамичном языке для Java Platform.
- Информация об установке и настройке PHP для разработки приложений Project Zero и о новых PHP-расширениях для Project Zero (EN).
- Дополнительные статьи и учебные руководства по Project Zero на developerWorks (EN).
- Информация о Dojo - пакете инструментальных программ JavaScript и Dojo-виджетах (EN).
- Информация о Representational State Transfer (REST) в диссертации Роя Томаса Филдинга (Roy Thomas Fielding) "Архитектурные стили и дизайн сетевых программных архитектур" (EN).
- Подробная информация о JSON и поддержке JSON в Project Zero (EN).
- Информация об Eclipse - открытой платформе разработки (EN).
- Дополнительная информация о Web-браузере Firefox от Mozilla и плагине Poster (EN).
- Информация об Apache Derby - реляционной базе данных с открытыми исходными кодами, реализованной полностью на Java (EN).
- Информация об управляемой сообществом коммерческой разработке (Community-Driven Commercial Development - CD/CD) (EN).
- Статья "Сравнение ориентированных на ресурсы и ориентированных на действия Web-сервисов" (developerWorks, октябрь 2004 г.) (EN).
- Дополнительные статьи и учебные руководства по REST на developerWorks (EN).
-
RSS-фид для данной серии статей (дополнительная информация об RSS).
- В разделе developerWorks Architecture размещены ресурсы, необходимые для повышения квалификации в области IT-архитектуры (EN).
- Магазин с книгами по этой и другим техническим темам.
Получить продукты и технологии
-
Загружаемые файлы для Project Zero.
- Загрузите пробные версии продуктов IBM и освойте инструментальные средства разработки приложений и продукты промежуточного уровня DB2®, Lotus®, Rational®, Tivoli® и WebSphere®.
Обсудить
- Примите участие в обсуждении материала на форуме.
-
Принимайте участие в
форумах на
developerWorks Россия.
-
Принимайте участие в
блогах developerWorks
и подключайтесь к сообществу
developerWorks.
Роланд Барсиа (Roland Barcia) - дипломированный специалист по информационным технологиям для IBM Software Services for WebSphere в области New York/New Jersey Metro. Он является соавтором IBM WebSphere: Развертка и дополнительные конфигурации. Чтобы узнать больше о Роланде, посетите его сайт.
Стив Имз (Steve Ims) является старшим инженером и руководителем группы разработки "ядра" системы времени исполнения Project Zero. Его можно найти на форумах Project Zero.