Пишем и отлаживаем компонент для GWT и Vaadin

Пишем и отлаживаем компонент для GWT и Vaadin

Фреймворки Google Web Toolkit и Vaadin достаточно хорошо себя показывают, когда вы просто используете их. Если вдруг вам понадобилось расширить их функциональность, то вам придётся серьёзно попотеть. В этой статье я хочу рассказать, как написать простой компонент на GWT, добавить к нему серверную часть Vaadin и использовать в своём приложении. Я не буду создавать некий совсем пустой GWT/Vaadin проект и с самого начала настраивать компиляцию GWT, вместо этого возьму приложение на базе CUBA.Platform, в котором и реализую сам компонент, а затем попробую в деле. Так будет видно, насколько хорошо всё впишется в настоящее приложение. Отдельное внимание я бы хотел уделить отладке компонента, поскольку она нетривиальна и всегда вызывает трудности у разработчиков.

Хочу предупредить, что не всё описанное в статье относится к GWT и Vaadin, часть шагов и приёмов применимы только в контексте использования CUBA.Platform, за счёт этого сильно упрощена настройка окружения и некоторые рутинные действия.

Подготовка окружения

Мы будем использовать для опытов пустой проект, созданный в CUBA Studio. CUBA — наша платформа для разработки бизнес приложений на Java, которая позволяет быстро создавать модель данных и интерфейс приложения, определять логику работы с данными и управлять правами пользователей. В основе UI платформы активно используется веб-фреймворк Vaadin, что позволяет нам реализовывать множество интересных задумок.

Для начала создадим модуль GWT, который будет компилироваться в JavaScript. Выполним действие 'Create web toolkit module' в Studio. Это простая вспомогательная операция, которую нет смысла выполнять вручную. Studio сгенерирует описатель GWT модуля AppWidgetSet.gwt.xml, директорию для модуля и пустой пакет, а также добавит в описание сборки build.gradle необходимые задачи.

Следующим шагом запустим действие 'Create or update IDE project files', чтобы сгенерировать файлы проекта IntelliJ IDEA, и отправимся писать код компонента в IDE.

Для программирования самого компонента нам не потребуется каких-то особенных возможностей IDE кроме подсветки Java кода, поэтому совсем необязательно использовать IntelliJ Idea, с таким же успехом мы можем использовать Eclipse или Netbeans. Благодаря Google Web Toolkit мы можем использовать знакомые Java инструменты, а это большое преимущество при разработке масштабных проектов.

Пишем компонент

Сам компонент будет довольно простым — поле рейтинга в виде 5 звёзд. Это поле ввода, в котором пользователь выбирает рейтинг при помощи мыши. У него есть состояние на сервере и отображение должно меняться при его изменении.

Он наследует базовый модуль CUBA.Platform и является отправной точкой всей клиентской части нашего приложения (той, что исполняется в браузере). По умолчанию реализации GWT компонентов должны располагаться в подпакете 'client'. Создадим пакет client и в нём подпакет ratingfield.

Первая деталь нашего компонента — виджет GWT. Класс RatingFieldWidget, который мы разместим в модуле web-toolkit:

Виджет представляет собой изолированный класс, отвечающий за отображение и реакцию на события. Он не должен знать о серверной части, он лишь определяет интерфейсы для работы с ней. В нашем случае это метод setValue и интерфейс StarClickListener.

Стоит отметить, что во всём коде виджета нет ни строки JavaScript, что довольно хорошо для больших и сложных компонентов. Но не забывайте, что этот Java код будет скомпилирован в JavaScript и вам могут быть недоступны многие части стандартной библиотеки Java, например рефлексия и ввод-вывод (полную информацию о совместимости смотри тут: www.gwtproject.org/doc/latest/RefJreEmulation.html).

Определяем внешний вид

Как вы могли заметить, в коде виджета нет упоминаний внешнего вида, кроме назначения имён стилей ключевым элементам. Этот приём постоянно используется при разработке компонентов и позволяет определять внешний вид в CSS на основе комбинаций стилей.

Для того, чтобы определить внешний вид нашего компонента, сперва, создадим файлы стилей. Для этого можем воспользоваться действием 'Create theme extension' для темы 'halo'. Эта тема использует вместо иконок глифы шрифта FontAwesome, чем мы и воспользуемся. Studio создаст пустые файлы SCSS для наших экспериментов в каталоге themes модуля web.

Стили каждого компонента принято выделять в отдельный файл componentname.scss в каталоге components/componentname в формате примеси SCSS:

Пара слов об SCSS. Это формат описания CSS стилей, позволяющий использовать переменные, примеси и вычисляемые значения. Он активно используется во многих веб-фреймворках, в Vaadin 7 — это базовый формат тем приложения. В приложении CUBA.Platform мы можем просто использовать этот формат, поскольку Studio берёт на себя грязную работу по организации сборки тем SCSS.

Формат описания в виде примеси поможет нам, если у компонента появятся наследники с другим primary-stylename. Мы просто включим стили предка при помощи SCSS include.

Для наших звёзд мы используем два глифа FontAwesome — 'fa-star' и 'fa-star-o'. Сам CSS довольно прост и включает лишь символы звёзд в двух состояниях и курсор мыши для них.

Для переключения темы в приложении нужно выбрать halo на странице Project Properties в CUBA.Studio.

Добавляем серверную часть

До этого момента мы могли использовать написанный нами виджет в каком-нибудь GWT приложении, поскольку он никак не зависел от сервера. Теперь давайте поговорим про фреймворк Vaadin и его сервер-ориентированную модель. Она имеет пару особенностей:

— всё состояние компонентов и полей ввода хранится на сервере и может быть восстановлено даже после полного обновления страницы или обрыва связи с сервером — весь полезный код приложения, за исключением клиентской части, исполняется на сервере

То есть компоненты Vaadin скрывают от разработчика то, как они работают в браузере и беспечный Java разработчик HTML/CSS никогда и не видит (ну или почти никогда не видит, а то вдруг ещё полезет писать компоненты).

Создадим пакет com.haulmont.ratingsample.web.toolkit.ui в модуле web. В нём мы разместим код нашего компонента RatingField. Унаследуем класс от класса Vaadin AbstractField, определяющего базовую логику работы полей ввода.

Ключевые серверные составляющие компонента Vaadin:

1) Класс компонента RatingField определяет API для серверного кода, различные get/set методы для работы, слушатели событий и подключение источников данных. Прикладные разработчики всегда используют в своём коде методы этого класса.

Важный момент — классы состояния и rpc должны быть расположены в подпакете 'client', так цепкие лапы компилятора GWT без проблем доберутся до них, чтобы создать их JavaScript представление для клиентского кода. Помимо этого, классы не должны использовать код, который не может быть скомпилирован GWT.

Вот теперь настал момент связать наш клиентский код с серверной частью. Эту роль в Vaadin выполняют классы-коннекторы. Они размещаются рядом с классами виджетов. Класс коннектора аннотируется Connect(ComponentName.class), так и задаётся соответствие клиентской части серверной:

Пробный запуск

Чтобы всё это попробовать в деле, выполним несколько подготовительных шагов:

1) Создадим БД для приложения из меню Studio: Run — Create database 2) Создадим экран для размещения компонента в модуле web:

3) Добавим экран в меню приложения: Main menu — Edit

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

Запускаем приложение из Studio: Start application server, переходим на http://localhost:8080/app смотреть результат:

Радуемся полнофункциональному компоненту, который мы теперь можем использовать из нашего Java кода на сервере. Весь код пригоден для использования в любом Vaadin приложении.

Отладка в браузере

Мы будем рассматривать только отладку кода виджетов, поскольку отлаживать код Java компонентов на сервере довольно просто.

Отладка любого GWT кода совсем нетривиальна и требует аккуратности. Для отладки воспользуемся режимом SuperDevMode. Необходимо, чтобы ваш проект собирался с GWT 2.5.1 или старше. Этот режим предполагает использование сопоставления Java кода с JavaScript кодом в браузере (source-maps, см developer.chrome.com/devtools/docs/javascript-debugging#source-maps). То есть вы будете видеть и отлаживать Java код в браузере, но с некоторыми ограничениями.

  1. Вы запускаете сервер com.google.gwt.dev.codeserver.CodeServer отдающий на сторону браузера соответствие JS кода и Java кода, а также собирающий ваш виджетсет при обновлении страницы
  2. Открываете приложение с параметрами ?debug&superdevmode
  3. Настраиваете Developer Tools, F12, в нижнем правом углу есть кнопка открытия настроек. Отметить опцию Enable source maps
  4. Обновите страницу, откройте в Developer Tools вкладку Sources. Там должны быть показаны все Java классы GWT виджетов. В отладчике Chrome можно ставить точки останова, смотреть переменные и выполнять выражения.
  5. При изменении кода виджета в проекте достаточно обновить страницу, виджетсет будет пересобран и подхвачен браузером. Это позволяет на лету видеть изменения кода виджета, что заметно ускоряет разработку.

2) Выполним в Studio действие 'Create or update IDE project files', чтобы Idea увидела новую зависимость 3) Создаём новую конфигурацию запуска в Idea с типом Application и следующими параметрами:

Main class: com.google.gwt.dev.codeserver.CodeServer VM options: -Xmx512M Use classpath of module: app-web-toolkit Program arguments: -workDir C:\Users\yuriy\work\ratingsample\build\tomcat\webapps\app\VAADIN\widgetsets -src C:\Users\yuriy\work\ratingsample\modules\web\src -src C:\Users\yuriy\work\ratingsample\modules\web-toolkit\src com.haulmont.ratingsample.web.toolkit.ui.AppWidgetSet

Пути к каталогам build\tomcat\webapps\app\VAADIN\widgetsets, modules\web\src и modules\web-toolkit\src необходимо заменить на свои.

4) Выполняем в Studio: Run-Start application server 5) Запускаем ранее созданную конфигурацию GWT в Idea 6) Переходим по адресу http://localhost:8080/app?debug&superdevmode 7) Открываем DevTools в Chrome и видим свой Java код:

Плюс этого способа в том, что он не требует особой поддержки от IDE, быстро работает и позволяет отлаживать код прямо в браузере. К минусам стоит отнести то, что вам недоступно выполнение Java кода во время отладки, а также точки останова с условиями на Java, да и непривычно это как-то. Есть ещё жирный минус — старые браузеры совсем не умеют source-maps, что затрудняет нормальную отладку.

Вместо заключения

GWT — очень сильный и развитый веб-фреймворк, в последние годы он активно используется большим числом разработчиков по всему миру. Google не забывает про своё детище и активно применяет его, совсем недавно они выпустили Gmail Inbox (http://gmailblog.blogspot.ru/2014/11/going-under-hood-of-inbox.html), который интенсивно использует GWT для веб интерфейса.

Vaadin тоже не отстаёт и сейчас является одним из лучших вариантов серверной части для GWT. Сервер-ориентированная модель позволяет быстрее разрабатывать, проще сопровождать приложения и меньше переживать за безопасность данных. Сложность доработки функционала GWT и Vaadin довольно изолирована и не следует её пугаться, преимущества этих технологий для разработки перекрывают все их минусы.

Мы активно используем Vaadin вот уже 5+ лет и уверены в нём. Всем советую рассматривать его, в качестве основного фреймворка для построения веб-приложений, особенно бизнес направленности.

📎📎📎📎📎📎📎📎📎📎