Статьи

Генерация графического интерфейса на основе модели с OpenXava

Это история о том, как легко или просто создать пользовательский интерфейс, о хороших пользовательских интерфейсах, не работая на них.

Эта проблема

Когда-то вы создали действительно классное приложение для выставления счетов. У вашего замечательного приложения был гибкий символьный интерфейс MS-DOS (или Unix, или AS / 400 , или HOST ), но ваши пользователи требовали интерфейс Windows: более красивый и более простой в использовании. Итак, вы переписали свое приложение, чтобы иметь пользовательский интерфейс Windows. Все в порядке, но затем ваши пользователи попросили вас о мультиплатформенном приложении, поэтому вы переписали ваше приложение на Java с помощью AWT , но ваш пользовательский интерфейс был плохим. Затем вы переписали его снова, используя Swing . Опять все ок — а может и нет. Пользователи начали запрашивать веб-приложение, поэтому вам нужно было использовать JSPсоздать веб-интерфейс — но ваши пользователи просили об интеграции внутри порталов, поэтому вы адаптировали свое приложение для работы внутри порталов JSR-168 и, возможно, вы начали использовать JSF . И теперь ваши пользователи продолжают требовать лучшего пользовательского интерфейса; они требуют более богатого веб-интерфейса. К сожалению! Теперь вы должны снова переписать ваше приложение, используя AJAX или, может быть, JavaFX .

Сколько раз вам нужно переписывать ваше приложение, чтобы улучшить пользовательский интерфейс?

Решение

На первый взгляд, идеальное решение — иметь метод объявления абстрактного пользовательского интерфейса и несколько механизмов рендеринга для рисования пользовательского интерфейса с использованием различных технологий представления. Это неплохая идея, и было сделано много попыток хорошего качества в этом направлении; XSL / XML, XForms , XULи другие ищут абстрактный способ определения пользовательских интерфейсов. Но эти методы не так абстрактны. Можете ли вы создать приложение для Windows с XSL / XML? Можете ли вы определить приложение Flash с XForms? Может быть. Но часто каждый новый механизм представления имеет свое собственное «абстрактное» определение пользовательского интерфейса. Несмотря на этот комментарий, я надеюсь, что в ближайшем будущем у нас будет универсальный способ определения пользовательских интерфейсов, по крайней мере, для бизнес-приложений. Может быть, какая-то эволюция XForms или … что-то.

С другой стороны, я рекомендую альтернативное решение: не определять «пользовательский интерфейс» вообще.

Да, вы можете создавать сложные бизнес-приложения без определения вашего пользовательского интерфейса. Как? Просто: вы можете получить свой пользовательский интерфейс из вашей модели; то есть из классов вашей системы, которые определяют структуру данных и поведение, связанное с этими данными. Я использую эту технику в течение семи лет, и я заметил, что переход с Swing на Web был плавным, и, кроме того, время разработки было сокращено, поскольку мне не нужно рисовать пользовательские интерфейсы.

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

Это может помочь увидеть пример.

Простой пример

Эти примеры основаны на платформе OpenXava .

Для первого примера у вас может быть класс для клиента, например, такой:

@Entity
public class Customer {

private int number;
private String name;

public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}

И из этого кода вы получите приложение, подобное показанному на рисунке 1, с полным пользовательским интерфейсом, плюс поведение CRUD и режим списка для просмотра, упорядочивания и фильтрации объектов; генерировать отчеты в формате PDF; и экспортировать в Excel. Вы получаете все это без дополнительного кода, только вышеупомянутый класс Customer.

OpenXava CRUD модуль для Заказчика
Рисунок 1. Модуль OpenXava CRUD для клиента

Вам нужно только написать вышеуказанный файл Customer.java , добавить его в существующее приложение OpenXava, повторно развернуть приложение на сервере приложений Java, открыть браузер и перейти по адресу http: // localhost: 8080 / Invoicing / xava / module.jsp ? application = Invoicing & module = Customer, чтобы увидеть результат работы.

Создание приложения OpenXava с нуля — простая ваниль. Загрузите последнюю версию OpenXava и распакуйте ее. Затем перейдите в папку openxava-3.0.x / workspace / OpenXavaTemplate и выполните следующую цель ant:


/java/openxava-3.0.2/workspace/OpenXavaTemplate> ant -f CreateNewProject.xml
Buildfile: CreateNewProject.xml
[input] What is your project name?
Invoicing
[input] What is the datasource?
InvoicingDS

Как видите, при сборке запрашивается имя проекта и источник данных. Просто введите Invoicing и InvoicingDS. Теперь у вас есть новый проект OpenXava с именем Invoicing в вашей рабочей области. Перейдите в папку src и создайте там пакет com.mycompany.invoicing.model. Внутри него помещен код вышеупомянутого класса Customer. Вы можете развернуть это приложение в контейнере сервлетов, используя целевой объект deployWar Ant или используя generatePortlets для развертывания на портале JSR-168 , таком как Liferay, JetSpeed ​​или WebSphere Portal. Конечно, вы должны определить источник данных с именем InvoicingDS на вашем сервере приложений. Если в вашей базе данных нет таблиц для ваших классов, вы можете использовать целевой объект Ant updateSchema для создания или обновления таблиц в базе данных.

Пошаговое руководство по созданию нового проекта OpenXava см. В главе 2 Справочного руководства по OpenXava .

Более сложный пример

Но что, если случай более сложный, такой как счет-фактура, и автоматическое создание графического интерфейса не кажется подходящим? Затем вместо того, чтобы определять пользовательский интерфейс для счета-фактуры вручную, мы можем дать системе некоторые подсказки и оставить ее для продолжения создания пользовательского интерфейса. Например, вы можете добавить аннотации в свой класс Invoice. Давайте создадим счет, который будет содержать год, номер, дату, комментарий, сумму сумм, процент НДС и НДС, ссылку на клиента, сбор данных и сбор доставок. Для этого нам нужны следующие классы: Invoice, Customer, InvoiceDetail и Delivery. У нас уже есть код для Customer, поэтому давайте посмотрим код для Invoice:

@Entity                                                         // 1
@View( // 2
members=
"year, number, date;" +
"comment;" +
"customer { customer }" +
"details { details }" +
"amounts { amountsSum; vatPercentage; vat }" +
"deliveries { deliveries }"
)
public class Invoice {

@Column(length=4) // 3
private int year;

@Column(length=6) // 3
private int number;

private Date date;

@Column(length=80) // 3
private String comment;

@ManyToOne // 4
private Customer customer;

@OneToMany(mappedBy="invoice") // 5
@ListProperties( // 6
"serviceType, product.description," +
"product.unitPriceInPesetas, quantity," +
"unitPrice, amount")
private Collection<InvoiceDetail> details;

@OneToMany(mappedBy="invoice") // 5
private Collection<Delivery> deliveries;

// Getters and setters
...

// Calculated properties
@Digits(integerDigits=12, fractionalDigits=2) // 7
public BigDecimal getAmountsSum() { ... }

@Digits(integerDigits=12, fractionalDigits=2) // 7
public BigDecimal getVat() { ... }

@Digits(integerDigits=12, fractionalDigits=2) // 7
public BigDecimal getTotal() { ... }

}

 

Этот класс не определяет пользовательский интерфейс (как в случае с XUL или XForm); вместо этого он только дает некоторую информацию о предпочтительном способе размещения данных. Это делается с помощью аннотаций JPA и OpenXava. Давайте рассмотрим аннотации:

  1. @Entity (JPA): помечает этот класс как постоянный, что означает, что в базе данных есть таблица для хранения данных счетов.

  2. @View (OX): с помощью элемента @View вы определяете элементы (свойства, ссылки или коллекции) модели для отображения и распределение данных в пользовательском интерфейсе; используя {}, вы указываете предпочтительный способ классификации данных.

  3. @Column (JPA): @Column используется механизмом JPA для получения информации о столбце базы данных для выполнения сопоставления ИЛИ и генерации DDL, если это необходимо. OpenXava использует длину @Column для расчета размера редактора в пользовательском интерфейсе.

  4. @ManyToOne (JPA): это стандартный способ определения отношения «многие к одному» для объекта. То есть простая ссылка от сущности к другой. OpenXava использует его для создания пользовательского интерфейса для отображения, поиска, изменения и создания новых объектов ссылочной сущности.

  5. @OneToMany (JPA): эта аннотация является стандартным способом определения отношения «один ко многим» для объекта. Это коллекция других объектов. OpenXava использует его для создания пользовательского интерфейса для управления коллекцией; это включает в себя элементы просмотра; добавление новых; удаление, редактирование, заказ и поиск в коллекции; создание отчетов в формате PDF из элементов коллекции; экспорт в Excel; и так далее.

  6. @ListProperties (OX): эту аннотацию можно использовать для определения свойств, отображаемых в пользовательском интерфейсе для коллекции.

  7. @Digits : эта аннотация взята из фреймворка Hibernate Validator . OpenXava распознает аннотации Hibernate Validator и в этом случае использует целочисленные значения и дробные значения для вычисления размера редакторов пользовательского интерфейса.

Исходя из этих подсказок, OpenXava создает пользовательский интерфейс, подобный показанному на рисунке 2. Вам нужно только написать классы, развернуть приложение и перейти по адресу http: // localhost: 8080 / Invoicing / xava / module.jsp? Application = Выставление счетов и модуль = Клиент . Больше никаких шагов не требуется.

Модуль OpenXava для инвойса
Рисунок 2. Модуль OpenXava для Invoice

Вы можете увидеть, как этот интерфейс по-прежнему отображается в модели, а аннотации OpenXava — это всего лишь группа простых абстрактных советов. Например, разделы — элементы в фигурных скобках — указывают, как информация связана для ее отображения. В этом случае каждый раздел соответствует вкладке в пользовательском интерфейсе, но другой визуализатор может использовать деревья или какой-либо другой элемент управления пользовательского интерфейса для доступа к данным разделов, включая отображение всех данных на одном экране. Особенно мощное средство визуализации может позволить пользователю выбрать точный способ представления разделов (вкладок, деревьев или других).

Что произойдет, если ваша модель данных изменится? В этом случае вам нужно только добавить нужные свойства, ссылки и коллекции, а затем выполнить целевой объект Ant updateSchema, чтобы обновить базу данных, развернуть приложение (с deployWar) и обновить браузер. Если вы используете Eclipse для JEE, вы можете пропустить шаг развертывания.

Вывод

Автоматическая генерация пользовательского интерфейса из модели не является универсальным решением; иногда разработка пользовательского интерфейса вручную действительно является лучшей альтернативой. Но во многих случаях (как и в случае с бизнес-приложениями) высокий процент пользовательского интерфейса приложения может быть создан автоматически с действительно хорошим результатом.

Автоматическая генерация пользовательского интерфейса имеет следующие преимущества:

  • Эволюция интерфейса : поскольку вы не пишете интерфейс с использованием определенной технологии, миграция приложения на другую технологию представления очень проста (например, переход от чисто HTML-приложения к AJAX).

  • Производительность : вы освобождаете своих разработчиков от трудоемкой работы. В конце фреймворки MVC остаются фреймворками MC.

И самый важный вопрос: это не теоретический подход, а прагматичный. В моей компании мы с большим удовольствием использовали эту технику в течение семи лет. Во-первых, у нас есть неопытные программисты, продуктивно работающие с Java, без необходимости изучать нюансы Swing. У нас также есть такие же программисты, которые разрабатывают приложения для веб-портала без необходимости изучать JSP, JSF, JSR-168 или другие технические вещи.

Считаете ли вы, что для счастья ваших разработчиков необходимо использовать Swing, JSP, JSF или AJAX? Думаю, нет. Когда разработчики привыкли к автоматической генерации пользовательского интерфейса, они начинают ненавидеть ручную разработку (даже с использованием GUI-компоновщика) пользовательских интерфейсов.

Ресурсы

Эти рамки и технологии имеют дух этой статьи:

  • OpenXava : эта платформа автоматически генерирует бизнес-приложения из простых классов Java с аннотациями, включая сложные пользовательские интерфейсы. Пример в этой статье использует синтаксис OpenXava. Если вас интересует полный синтаксис для генерации пользовательского интерфейса, вы можете посмотреть документацию OpenXava .
  • Trails генерирует приложения из аннотированных POJO.
  • JMatter создает бизнес-приложения для рабочих групп на основе классов моделей.
  • NakedObjects генерирует пользовательский интерфейс из объектов Java; классы должны следовать некоторым правилам.
  • RomaFramework генерирует приложения из POJO, используя файлы XML для настройки представления.
  • MDA : Суть MDA заключается в создании законченного приложения (а следовательно, и интерфейса) из модели UML. Основным элементом дизайна программного обеспечения является модель, и пользовательский интерфейс генерируется. (Возможно, чрезмерная ориентация на генерацию кода в MDA создает инструменты, которые не являются гибкими, с точки зрения разработчика.)