четверг, 11 ноября 2010 г.

Spring Roo. Что за зверь?

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

Установка
  1. Необходимо скачать набор бинарных утилит - это ядро самого Spring Roo - http://www.springsource.com/products/spring-community-download. Необходимо добавить /bin папку данных утилит в PATH.
  2. Если вы работаете под Eclipse, то поставить SpringSource Tool Suite, как плагин или в виде отдельной сборки - http://www.springsource.com/developer/sts. Я рекомендую вариант плагина.
  3. Maven - http://maven.apache.org/download.html, а также плагин к Eclipse m2Eclipse.
Вы можете просмотреть видео по установке Spring Roo, если возникли какие-то затруднения http://s3.springsource.com/MRKT/roo/2010-01-Five_Minutes_Roo.mov.

Первый проект
Инструкция по созданию тестового проекта представлена на http://static.springsource.org/spring-roo/reference/html/intro.html#intro-first-steps. Думаю, что там нет ничего сложного.

Мой опыт работы
Консоль
Центральным элементом Roo является её консоль. В консоли качественно реализована функция suggest. Единственное, что иногда консоль может выдавать большее количество подсказок.

Использование аспектов AspectJ и кодогенерация
В Roo аспекты использованы очень удачно. Они генерируются автоматически по аннотациям классов. Если какой-либо из этих аспектов не нужен, то необходимо удалить соответствующую аннотацию. В случае изменения данных в классе, эти аспекты автоматически пересоздаются. Редактировать вручную их можно, но изменения не сохранятся, при любом изменении произойдет перегенерация аспектов.
Например, Roo может выносить в аспекты следующие вещи:
  • геттеры и сеттеры
  • метод toString (с возможностью настройки того, какие поля будут в нем прописываться)
  • базовые вещи для Entity классов. Это например id поле, аннотация того, что класс является сущностью. EntityManager и т.д.
  • стандартные методы контроллеров
  • генерация finder-методов. Roo может генерировать практически любые комбинации полей, по которым необходимо искать. 
Единственное, что тут непонятно для меня, так это почему автоматически не генерируются методы equals и hashCode.  UPDATE: Генерация данных методов вынесена в отдельный плагин http://code.google.com/p/spring-roo-equals-roo-addon/. Возможно, этот плагин войдет в новый релиз.
С аспектами возможно появление непредсказуемых багов в плане отладки. Там возможны некоторые затруднения с дебагом.

Добавление полей сущностям
Эта функция реализована на ура. Можно добавлять новые поля, как из консоли, так и из IDE. Roo все подхватывает и исправляет.

Scaffold
Roo предоставляет возможность Scaffold. Реализуется это при помощи установки аннотации @RooWebScaffold на класс модели. Scaffold - это автоматическая генерация UI по моделям. Это функция очень хороша, когда надо создать скелет UI в проекте с новыми технологиями. Можно посмотреть, как все работает и исправить на свой вкус. 
Сам скаффолд генерируется в виде *.jspx файлов и небольшой библиотечки тегов.
Хотя с исправлением скаффолда сейчас не все гладко, например, если вы в скаффолде укажете русские символы, то при следующем обновлении увидите заместо них "???". Это связано с тем, что проект ещё сыроват, особенно в плане поддержки других языков.
Естественно, что в каких-либо реальных проектах будет просто необходимо отказываться от скаффолда. 
С версии 1.1.0 возможен scaffold при помощи GWT.

Maven
Maven используется, как для поддержания зависимостей проекта от сторонних библиотек, так и для запуска проекта в сервлет-контейнере. 

Обновление
Начинал я работу со Spring Roo с версии 1.0.0. Во время моей работы Roo успел обновиться до версии 1.1.0. Изменения очень сильные, по сути пришлось пересоздавать проект. Подозреваю, что такая нестабильность сохранится и в ближайшее время, поэтому для серьезных проектов использовать Roo рано. 

Документация
Как и в Spring, документация здесь далеко не всегда полная и полезная.

Баги
Сталкивался с парой багов, связанных с UTF-8 кодировками. Они до сих пор не решены в 1.1.0 и будут решены в 1.1.1. Одна из них, кстати, благодаря мне.

19 комментариев:

  1. А можете описать, процесс работы с roo: для чего используете и кратко план работы?

    ОтветитьУдалить
  2. Я сейчас пишу систему поддержки видеоархива университетского телеканала.
    Roo - это довесок над Спрингом, это не новый фреймворк, поэтому выкинуть его не проблема. Этому даже посвящена одна глава мануала.

    Типичный план работы:
    -создаешь проект
    -в консоли настраиваешь persistence, выбираешь провайдера, субд
    -одной коммандой настраивашь logging
    -в консоли создаешь сущности
    -в консоли добавляешь им поля с констрейнтами
    -запускаешь генерацию скаффолда. если это не gwt, то создаются jspx файлы и контроллеры с типичными методами
    -mvn tomcat:run - приложение работает

    Email, JMS и прочее настраивается одной командой и потом уже допиливается. Все зависимости подключаются автоматом.

    В общем, если все зависимости Maven уже скачал, то создание нового проекта и его запуск занимает очень мало времени.

    Самое интересное ожидает нас впереди, когда появится куча аддонов к Roo. Уже сейчас в консоли есть функция загрузки таких аддонов, но самих аддонов пока нет.
    Я уверен, что в ближайшее время появятся хорошие аддоны для авторизации, генерации админки и т.д и т.п.
    Я говорю судя из своего опыта работы с Ruby on Rails, что в аддонах скрыта колоссальная сила.

    ОтветитьУдалить
  3. Чтобы сейчас в Spring сделать адекватную авторизацию приходится чуть ли не книги читать. Это неприемлемо в современном мире. Такие банальные вещи должны устанавливаться одной командой. Spring Roo развивается в данном ключе.

    ОтветитьУдалить
  4. Также я забыл упомянуть одну интересную особенность Spring Roo. Он не позволяет сделать класс с именем User :-), даже если задаешь другое имя для таблицы.

    ОтветитьУдалить
  5. Спасибо, но в туториале это есть и его я изучал.

    Меня больше интересует не создание болванки проекта, а работа с ним. Те. банально с начала привязка дизайна, как добавляются страницы и тп.

    Кстати, проект ведётся под какую версию?
    И по security в 1.1.0 вроде проблем не было, правда я использовал provider по-умолчанию.

    ОтветитьУдалить
  6. Spring roo делался с оглядкой на grails, это чувствуется во всем. Grails более зрелый проект, плагинов для него очень много, community сформировано. Внутри тот же spring и jpa.

    ОтветитьУдалить
  7. 2 serger:
    Я придерживаюсь той структуры, которую нагенерил Roo. Использую tiles.
    Проект веду на 1.1.0. С security и раньше было нормально. Он не изменился. Но мне надо создать свой класс юзера. Удивляет, что Spring по умолчанию предлагает забивать пользователей в xml файле.

    2 ruzhnikov:
    Все они друг на друга влияют. Мне нравится, что сейчас все фреймворки стремятся к увеличению продуктивности работы программиста.
    Хотелось бы, чтобы Spring стал проще, а разработка приложений на нем была бы возможна с минимальным чтением доков.

    ОтветитьУдалить
  8. А как реализуется "бизнес-логика"? И как она связывается с контроллерами. Или всё через finder`ы делаете?

    ОтветитьУдалить
  9. Поиск через finder'ы.
    Логику как раз прикручиваю и разбираюсь в связке контроллеров и GUI. Пока что в мануалах не нашел того, что ищу. Для преобразования данных с полей использую Converter'ы.
    Как разберусь - напишу статейку на примере создания блога.
    Часть логики в сервисах.

    ОтветитьУдалить
  10. Те контроллеры, которые генерит Roo в аспектах я скопировал в классы контроллеров. Это всвязи с тем, что Scaffold выкинул.
    Вот эти базовые методы в контроллере меня устраивают. Теперь мне нужно определить ряд методов, которые будут вызываться до попадания объекта в create или update метод.
    Пока что я использую каскадное сохранение в зависимых объектах. То есть например:
    class Foo {
    // .. аннотации
    @ManyToMany(cascade=CascadeType.PERSIST)
    List tags;
    }

    В контроллере я регистрирую конвертер, который переводит строку с тегами в объекты тегов, проверяя есть ли введенные теги в БД. Если же тега нет, то:
    Tag tag = new Tag();
    tag.setName(tagName);
    tags.add(tag);

    И потом тег каскадно сохраняется.

    ОтветитьУдалить
  11. > Как разберусь - напишу статейку на примере создания блога.
    Было бы супер!
    Я так понял, читая новость с новостного блога springsource, что они делают упор на то что в большинстве простых сайтов отдельный уровень сервисов не нужен. Вот это меня и обеспокоило. Увы нет достаточно сил сидеть долго разбираться, спасибо за статью и комментарии.

    ОтветитьУдалить
  12. Про сервисы я не помню такого. Они писали, что слой DAO не нужен и я согласен с ними :-).
    В моей системе пока только один сервис -авторизация.

    ОтветитьУдалить
  13. Хм.. В доке написано:
    "A web application will rarely require a services layer, as most logic can be placed in the web controller handle methods and the remainder in entity methods."
    Мб я не совсем точно перевожу. Но это немного смутило.

    ОтветитьУдалить
  14. Вы все верно переводите.
    Это действительно немного смущает и отходит от классической схемы. Но зачем усложнять там, где можно упростить?
    Например, для действия delete нет смысла создавать сервисный слой, когда нужно всего лишь выполнить простейшую проверку и вызвать соответствующий метод entityManager'а. Делать для этого DeleteFooService..?
    Я имею опыт работы с обоими подходами. На основной работе мы реализуем слой сервисов, правда они у нас называются бизнес-действия. В них происходят все персистентные изменения. Это удобно для бизнес-системы, где есть множество однотипных действий и хотелось бы их стандартизировать в виде сервисов (бизнес-действий).
    Другой опыт моей работы - это создание сайтов на Ruby on Rails. Там никаких сервисов нет и в помине и большинство действий выполняется в контроллерах. Такой подход идеален для веб-сайтов, где каждое действие в своем роде уникально. Вообще такой подход интуитивно понятнее.
    Видимо, Roo нацелен на проекты второго типа, то есть веб-сайты. Хотя кто мешает его использовать и для проектов первого типа..?

    ОтветитьУдалить
  15. Ну да. Там всё довольно интересно сделано, и мне как раз хочется понять методику, какую они предлагают. Тем более она отличается от канонов java.
    Но их доки и примеры скупы.
    Для Crud из туториалов всё идеально подходит, но CRUD в основном нужен в админке, ну для регистрации. А как создавать обычные страницы сайтов не привязанные к Entity, с такими примерами туго.
    И ещё, судя по таму как вы пользуетесь roo, у мня складывается мнение, что сам roo нужен только как болванка проекта. Ну и для генерации сущностей и CRUD, всё остальное удобнее делать ручками?!

    ОтветитьУдалить
  16. Кстати, в Grails с сервисами можно работать из под командной оболочки.

    ОтветитьУдалить
  17. Да, я использую его как болванку. Сейчас Roo дает не так много, как хочется. Он мне подходит для генерации сущностей, ну и как скелет проекта, легкого добавления фич (избавление себя от чтения мануалов).
    С примерами действительно туго, как и в Spring. Встречаю кучу вопросов на форумах из серии "как сделать такую-то фичу? я прочитал мануал, но ничего не понял".

    ОтветитьУдалить
  18. Вот дискуссия по поводу Roo
    http://www.techinfopad.com/spring/101900240-spring-roo-with-a-servicesdao-architecture.html

    ОтветитьУдалить