Вступление
С JSF мы все хорошо и давно знакомы. Работает вроде довольно неплохо. Существует ли достойная альтернатива? Будем рассматривать на основе следующих критериев:
- Реализация навигации по страницам.
- Локализация.
- Возможность использования бинов в слое представления (web-beans).
- Отображение полей сущности на поля формы.
- Конвертеры и валидаторы.
- Создание собственных компонентов.
- Наследование шаблонов.
- Литература, сообщество, применение в реальных проектах.
Версия Seam: 2.2.0.GA.
Сразу скажу, что опыт работы с GWT и Wicket у меня был довольно непродолжительный, так что статья не претендует на объективность (большинство возможностей этих технологий рассмотрено на основе документации, а не реальных прототипов). Пишите свои замечания – дополню/исправлю) Плюс, все технологии рассматриваются с точки зрения слоя представления для Seam, а не самостоятельно, что искажает их объективную оценку.
Ссылки
- Comparing Flex, Grails, GWT, Seam, Struts 2 and Wicket
- Which framework should I choose – Seam, Wicket, JSF or GWT?
- Is it true that Seam only works with JSF?
- Alternative View Layers Overview
JSF
Сайт: JavaServer Faces Technology
Рассматриваемая версия: 1.2
Последняя версия: 2.0
JSF – MVC-фреймворк, в основе которого лежит модель использования дерева компонентов. Для отрисовки дерева компонентов может использовать различные технологии (JSP, XUL, Facelets). Именно поддержка JSF в Seam реализована наиболее качественно.
Ссылки
Реализация навигации по страницам
Очень удобно. Через файл pages.xml.
<?xml version="1.0" encoding="UTF-8"?> <pages xmlns="http://jboss.com/products/seam/pages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.0.xsd"> <page view-id="/ajax/*"> <navigation> <rule if-outcome="error"> <redirect view-id="/ajax/common/message.xhtml"/> </rule> <rule if-outcome="fatal"> <redirect view-id="/ajax/common/message.xhtml"/> </rule> </navigation> </page> ... </pages>
Помимо самой навигации можно задать ограничения системы безопасности (<restrict>#{…}</restrict>). Есть возможность использовать EL-выражения, а значит и обращаться к бизнес логике приложения для осуществления сложной навигации. Возможна разбивка на более мелкие файлы для большего контроля (через настройки в components.xml).
<navigation:pages> <navigation:resources> <value>WEB-INF/pages/advertising-campaign.xml</value> <value>WEB-INF/pages/action.xml</value> <value>WEB-INF/pages/admin.xml</value> ... </navigation:resources> </navigation:pages>
Локализация
Поддерживает локализация на основе properties-файлов с локализованным текстом. В зависимости от локали используется тот или иной properties-файл.
Пример:
messages_ru.properties
menu.navigation=Навигация menu.sign-in=Войти menu.log-out=Выйти menu.admin=Администрирование
messages_en.properties
menu.navigation=Navigation menu.sign-in=Sign In menu.log-out=Logout menu.admin=Administrate
some.xhtml
<div>#{messages['menu.navigation']}</div>
Ссылки
Возможность использования бинов в слое представления (web-beans)
Производится с помощью EL-выражений. Обращение производится по имени Seam-компонента.
Пример:
<div> <h4>#{messages['show-material-description-field']}</h4> <h:outputText value="#{actionUserAction.actionUserMessage.materialDescription}" /> </div>
Отображение полей сущности на поля формы
Так же как и в предыдущем пункте используются EL-выражения. Выглядит всё очень прозрачно.
Пример:
UserEditAction.java
@Scope(ScopeType.EVENT) @Name("userEditAction") public class UserEditAction { private User editedUser; ... }
user_edit_action.xhtml
<div> <h:outputLabel for="firstName">Имя:</h:outputLabel> <h:inputText id="firstName" value="#{userEditAction.editedUser.person.firstName}" required="true" /> <h:message styleClass="error" for="firstName" /> </div>
Конвертеры и валидаторы
Есть большой набор и того и другого. Seam расширяет стандартный набор конвертеров и валидаторов своими.
Пример конвертера:
TrimConverter.java
@Name("trimConverter") @BypassInterceptors @org.jboss.seam.annotations.faces.Converter public class TrimConverter implements Converter { public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) { return s.trim(); } public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) { return (String) o; } }
some.xhtml
<h:inputText id="firstName" value="#{userEditAction.editedUser.person.firstName}" required="true" converter="trimConverter" />
Ссылки
Создание собственных компонентов
Наследуемся от требуемого базового класса и реализуем нужный нам функционал.
Пример:
AjaxRendererComponent.java
public class AjaxRendererComponent extends UIComponentBase { @Override public String getFamily() { return "project.AjaxRendererComponent"; } @Override public void encodeBegin(FacesContext context) throws IOException { ... ResponseWriter writer = context.getResponseWriter(); writer.startElement("div", this); writer.writeAttribute("id", containerId, null); if (containerClass != null) { writer.writeAttribute("class", containerClass, null); } writer.startElement("span", this); writer.writeAttribute("class", "hidden ajax-template", null); writer.append(template); writer.endElement("span"); AjaxRenderer ajaxRenderer = (AjaxRenderer) Component.getInstance("ajaxRenderer"); writer.startElement("span", this); writer.writeAttribute("class", "ajax-content", null); writer.append(ajaxRenderer.renderBody(template, attributes)); writer.endElement("span"); writer.endElement("div"); } }
faces-config.xml
<component> <component-type>project.AjaxRendererComponent</component-type> <component-class>project.tag.AjaxRendererComponent</component-class> </component>
project.taglib.xml
<tag> <tag-name>ajax-renderer</tag-name> <component> <component-type>project.AjaxRendererComponent</component-type> </component> </tag>
Однако гораздо чаще используются xhtml-тэги.
Пример:
project.taglib.xml
<tag> <tag-name>status</tag-name> <source>../tags/html/status.xhtml</source> </tag>
Ссылки
Наследование шаблонов
Наверное самая крутая часть JSF это его шаблонный движок. Можно выстраивать иерархии страниц, указывать в шаблонах заменяемые блоки, использовать тэги.
Пример:
base.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" xmlns:ui="http://java.sun.com/jsf/facelets"> <head> <title> <ui:insert name="title">Main | Project</ui:insert> </title> </head> <body> <ui:insert name="content" /> </body> </html>
user_information.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" template="/WEB-INF/template/base.xhtml"> <ui:define name="title">User page | Project</ui:define> <ui:define name="content"> Some user info. </ui:define> </ui:composition>
Литература, сообщество, применение в реальных проектах
Очень обширный список книг, статей и форумов. Используется в основном в очень крупных проектах.
Ссылки
- JSF for nonbelievers
- JSF Programming Resources
- Internet facing JSF Deployments In the Real World
- Rethinking JSF – The Real Problem
Итог
Была рассмотрена версия 1.2, в то время как сейчас уже можно пробовать 2.0. Хотя список изменений меня не впечатлил.
Плюсы:
- индустриальный стандарт, соотвественно не должен загнуться;
- очень хороший шаблонный движок;
- удобный механизм конвертеров и валидаторов;
- наилучшая поддержка в Seam.
Минусы:
- индустриальный стандарт, соотвественно очень медленно развивается;
- низкая скорость отрисовки/отдачи страницы по сравнению с другими технологиями;
- периодические проблемы с деревом компонентов.
Ссылки
Wicket
Сайт: Apache Wicket – Home
Рассматриваемая версия: 1.4
Последняя версия:1.4
Wicket – это компонентно-ориентированный веб-фреймворк от Apache. Основные фишки Wicket’а (исходя из описания):
- простота использования;
- почти полный отказ от XML;
- безопасность (весь код в Java);
- и т.д.
Ссылки
Реализация навигации по страницам
Навигация осуществляется с помощью ручных редиректов. Никакого глобального файла-конфигурации нет.
Пример перехода на Wicket-страницу:
public void onClick() { getRequestCycle().setRedirect(true); setResponsePage(WhereEverYouWantToRedirect.class); }
Каждой Wicket-странице соответствует свой Java-класс, который инициализирует её.
Пример перехода на не-Wicket-страницу:
public void onClick() { getRequestCycle().setRequestTarget(new RedirectRequestTarget("http://www.another-web-site.com") ); }
На класс страницы можно повесить @Restrict аннотацию. Правда пока не понятно как будет обработана ошибка и как это взаимодействует с иерархией страниц.
Пример:
@Restrict(...) public class HomePage extends WebPage { ... }
Локализация
Так же как и в JSF основана на properties-файлах с данными для каждой локали. Для получения/установки локали используются методы Locale.getDefault()_/_Locale.setDefault(Locale) соответственно.
Пример:
<!-- "Hello" - значение по-умолчанию в случае, если ключ "helloworld" не найден --> <wicket:message key="helloworld">Hello</wicket:message> <input type="submit" value="Default text" wicket:message="value:helloworld"/>
В указанном выше примере производится поиск ключа helloworld в соответствующем properties-файле. Выбор properties-файла осуществляется на основе имени класса компонента и текущей страницы. Сначала ищется properties-файл для текущей страницы, если нужный ключ не найден производится поиск в properties-файле компонента (поиск идёт сверху-вниз: страница -> компонент). Если страница или компонент являются наследниками другого класса и ключ не найден, то поиск пойдёт по всей иерархии. Если ключ не будет найдет, то производится поиск в properties-файле всего приложения.
Ссылки
Возможность использования бинов в слое представления (web-beans)
Пока обнаружил только связку через Java. Т.е. весь динамический вывод и все привязки (bindings) идут в Java-классе, соответствующем странице. Поддерживаются Seam’овские биекции. Привязка идёт на основе атрибута wicket:id.
Пример:
MainPage.java
public class MainPage extends WebPage { @In private Identity identity; public MainPage() { add(new Label("message", new Model(identity.getCredentials().getUsername()))); } }
home.xhtml
<html> <body> <span wicket:id="message" id="message">Message goes here</span> </body> </html>
Ссылки
Отображение полей сущности на поля формы
В Wicket существует четыре основных способа для отображения сущности (модели) на форму:
- Simple Models
- Dynamic Models
- Property Models
- Compound Property Models
Пожалуй это самая интересная часть в Wicket)
1. Simple Models
Используется для отображения на странице статичных данных. В указанном ниже примере конструктор класса Label автоматически обернёт строку “Hello World\!”_ в _new Model(”Hello World\!”).
Пример:
test_page.xhtml
<span wicket:id="message">Message goes here</span>
TestPage.java
public class TestPage extends WicketExamplePage { public TestPage() { add(new Label("message", "Hello World!")); // равносильно // add(new Label("message", new Model("Hello World!"))); } }
2. Dynamic Models
Рассмотренный нами в пункте Возможность использования бинов в слое представления (web-beans) пример использует динамическую модель.
Пример:
add(new Label("message", new Model(identity.getCredentials().getUsername())));
Чтобы при отправке формы данные модели менялись на значения из полей формы необходимо для модели определить геттеры и сеттеры.
Пример:
personForm.add(new RequiredTextField("personName", new Model() { @Override public Object getObject() { return person.getName(); } @Override public void setObject(Serializable object) { person.setName((String) object); } }));
Однако, такая конструкция довольно громоздкая, когда надо указать несколько полей. В этом случае используется следующий тип отображения.
3. Property Models
Приведённая в предыдущем примере конструкция сокращается до одной строки.
Пример:
personForm.add(new RequiredTextField("personName", new PropertyModel(person, "name")));
Доступ к геттерам и сеттерам поля name_ объекта _person_ осуществляется с помощью рефлексии. Так же допускаются вложенные свойства. Например, _address.city_ эквивалентно цепочке вызовов _getAddress().getCity() на текущем объекте модели.
4. Compound Property Models
Данный вид отображения позволяет элементам-потомкам использовать модель связанную с контейнером, в котором они находятся. В качестве контейнера, например, можно использовать форму.
Пример:
Form personForm = new Form("aPersonForm", new CompoundPropertyModel(person)); personForm.add(new RequiredTextField("name")); personForm.add(new RequiredTextField("age", Integer.class));
Если нам необходимо использовать внутри контейнера элемент, не связанный с моделью, то нужно явно это указать (связать с ним пустую модель).
Пример:
personForm.add(new Label("non-compound-model-reference", new Model()));
Ссылки
Конвертеры и валидаторы
Конвертеры
Для базовых классов конвертация осуществляется автоматически. Есть возможность написать свой конвертер.
Пример:
URLConverter.java
public class URLConverter implements IConverter { public URLConverter() { } public Object convert(Object value, Class c) { if (value == null) { return null; } if (c == URL.class) { if (value.getClass() == URL.class) { return value; } try { return new URL(value.toString()); } catch (MalformedURLException e) { throw new ConversionException("'" + value + "' is not a valid URL"); } } return value.toString(); } public void setLocale(Locale locale) { } public Locale getLocale() { return Locale.getDefault(); } }
SomePage.java
add(new TextField("urlProperty", URL.class) { public IConverter getConverter() { return new URLConverter(); } });
Если мы хотим привязать конвертер к классу, то в классе приложения нужно переопределить метод newConverterLocator.
Пример:
WicketApplication.java
protected IConverterLocator newConverterLocator() { ConverterLocator converterLocator = new ConverterLocator(); converterLocator.set(URL.class, new URLConverter()); return converterLocator; }
Валидаторы
Есть встроенные валидаторы (по-правде я нашёл всего один). Задаются при создании компонента.
Пример валидатора для обязательного поля:
TextField firstNameComp = new TextField("firstName"); firstNameComp.setRequired(true);
Также можно написать свой валидатор.
Пример:
EitherInputValidator.java
public class EitherInputValidator extends AbstractFormValidator { private final FormComponent<a href="">page title</a> components; public EitherInputValidator(FormComponent f1, FormComponent f2) { if (f1 == null) { throw new IllegalArgumentException("FormComponent1 cannot be null"); } if (f2 == null) { throw new IllegalArgumentException("FormComponent2 cannot be null"); } components = new FormComponent<a href="">page title</a> { f1, f2 }; } public FormComponent<a href="">page title</a> getDependentFormComponents() { return components; } public void validate(Form form) { final FormComponent f1 = components<a href="0">page title</a>; final FormComponent f2 = components<a href="1">page title</a>; String f1Value = Objects.stringValue(f1.getInput(), true); String f2Value = Objects.stringValue(f2.getInput(), true); if ("".equals(f1Value) || "".equals(f2Value)) { final String key = resourceKey(components); f2.error(Collections.singletonList(key), messageModel()); } } }
SomePage.java
Form myForm = new Form("form"); FormComponent f1 = new TextField("firstName"); myForm.add(f1); FormComponent f2 = new TextField("lastName"); myForm.add(f2); myForm.add(new EitherInputValidator (f1, f2));
Ссылки
Создание собственных компонентов
В статье по указанной ниже ссылке приведён пример создания компонента Footer страницы. Для компонента создаётся слой представления (xhtml-файл) и слой логики (Java-класс). Основная идея стандартная: унаследоваться от базового компонента и добавить нужный функционал.
Ссылки
Наследование шаблонов
Насколько мне удалось выяснить нормального шаблонного движка в Wicket нет. Т.е., если мы хотим добавить на страницу какой-то фрагмент xhtml, то его надо оформлять как компонент и добавлять через Java. А для наследования страниц предлагается воткнуть какой-то костыль. Вообщем в этом плане всё плохо, имхо.
Ссылки
Литература, сообщество, применение в реальных проектах
Есть ряд книг, часть из глав посвящена интеграции с Seam. Сообщество достаточно обширное за счёт того, что продукт от Apache. Примеров применения в реальных проектах не нашёл)
Ссылки
Итог
Честно говоря я не впечатлён. Основная фишка Wicket это “мы не используем эти ужасные xml”. Но, блин, мне приходится строить страницу из Java (хотя GWT тоже этим грешит) и нет нормального шаблонного движка. Все пишут, что Wicket это круто, но нигде не написано в каких проектах он вообще используется, что наводит на определённые мысли.
Плюсы:
- минимум настроек;
- активно развивается (пока);
- быстрее JSF, судя по тестам.
Минусы:
- нет реальных проектов (хотя может я плохо искал);
- документация слабовата;
- сложно использовать бины в слое представления;
- нет нормального шаблонного движка и механизма тэгов.
Ссылки
- Apache Wicket
- Wicket is the most widely used Java Web Framework
- Wicket Ajax
- Seamless Wicket: Orchestrating your application
- Seam / JSF vs Wicket: performance comparison
- Wicket and Seam sitting in a tree
- Want an introduction to Seam?
- Wicket Examples
- A Wicket user tries JSF
GWT
Сайт: Google Web Toolkit
Рассматриваемая версия: 2.0
Последняя версия: 2.0
GWT – фреймворк от Google для разработки быстрых и надёжных RIA-приложений.
Реализация навигации по страницам
Собственно, как таковой навигации по страницам в GWT нет) GWT-приложение работает в рамках одной страницы динамически изменяя её содержимое. Соотвественно для управления переходами между страницами нужна нижележащая технология.
Локализация
Поддерживается статическая (осуществляется на этапе компиляции) и динамическая (осуществляется в процессе работы приложения) локализация. Поддерживаются параметризованные сообщения. Есть встроенная “склонялка” для правильного вывода сообщений с различными значениями переменной-числительного.
Значения по умолчанию (нелокализованные) задаются с помощью аннотаций.
Пример:
Создаётся Java-файл с переменными, которые мы хотим локализовать. В нём с помощью аннотации @DefaultStringValue указываются значения по-умолчанию.
ApplicationConstants.java
public interface ApplicationConstants extends Constants { @DefaultStringValue("Symbol") String symbol(); @DefaultStringValue("Price") String price(); @DefaultStringValue("Change") String change(); @DefaultStringValue("Remove") String remove(); @DefaultStringValue("Add") String add(); }
Затем для каждой локали создаётся свой properties-файл. Например, для немецкого языка нужно создать файл ApplicationConstants_de.properties.
Пример:
ApplicationConstants_de.properties
symbol = Symbol price = Kurs change = Änderung remove = Entfernen add = Hinzufügen
Также в Java-коде необходимо осуществить привязку сообщений к компонентам.
Пример:
SomeApplication.java
private ApplicationConstants constants = GWT.create(ApplicationConstants.class); public void onModuleLoad() { ... table.setText(0, 0, constants.symbol()); table.setText(0, 1, constants.price()); table.setText(0, 2, constants.change()); table.setText(0, 3, constants.remove()); }
Возможность использования бинов в слое представления (web-beans)
Для того, чтобы вывести в слой представления какие-то данные, необходимо сделать привязку через Java. В Seam есть встроенная поддержка GWT и, соотвественно, из кода GWT можно обращатся к Seam-контекстам. Взаимодействие работающего приложения с сервером построено на обращении клиента к различным сервисам по определённым URL (фактически получается REST-архитектура). Для обмена данными с сервером можно использовать следующие механизмы:
- Making Remote Procedure Calls (GWT RPC).
- Retrieving JSON Data via HTTP.
- Making Cross-Site Requests for JSONP.
Пример сервиса:
@Name("org.jboss.seam.example.remoting.gwt.client.MyService") public class ServiceImpl implements MyService { @WebRemote public String askIt(String question) { if (!validate(question)) { throw new IllegalStateException("Hey, this shouldn't happen, I checked on the client, " + "but its always good to double check."); } return "42. Its the real question that you seek now."; } public boolean validate(String q) { ValidationUtility util = new ValidationUtility(); return util.isValid(q); } }
Ссылки
Отображение полей сущности на поля формы
Стандартного механизма для отображения в GWT к сожалению нет. Но есть ряд сторонних расширений, которые позволяют его осуществить.
Пример (в случае использования gwittir):
private Binding binding = new Binding(); public void set(BoundWidget widget) { BookForm bookForm = (BookForm) widget; Book book = (Book) bookForm.getModel(); ... binding.getChildren().add(new Binding(book, "title", bookForm.titleText, "value")); }
Связываем свойство title объекта book со свойством value объекта titleText (класс TextBox).
Ссылки
Конвертеры и валидаторы
Конвертеры
По конвертерам информации не нашлось. Однако, они особо и не нужны, т.к. весь код мы пишем на Java, а задачу преобразования данных JavaScript <-> Java решает компилятор GWT.
Валидаторы
Как ни странно, но встроенных валидаторов в GWT нет, зато есть сторонний фреймворк gwt-validation.
Пример:
// Contains the validation messages. Fully localizable! ValidationMessages messages = new ValidationMessages(); ValidationProcessor validator = new ValidationProcessor(messages); // We might have some TextBox that should only contain numeric values from 0 to 15 validator.addValidators("number", new IntegerValidator(numberTextBox, 0, 15) .addActionForFailure(new FocusAction()) //Adding an action in case of a validation failure );
Ссылки
- GWT Validation Framework based on the JSR303
- gwt-validation
- GWT Server Side Validator
- Input Validation with GWT
- A Simple GWT Validation Framework Using Great Design Patterns And MVP
Создание собственных компонентов
Опять же типичная схема: наследуемся и реализуем то, что нужно.
Пример (самый простой случай):
MyComponent.java
public class MyComponent extends Composite { private Button dialogButton = new Button("Show Dialog"); private Button popupButton = new Button("Show Popup"); public MyComponent(){ VerticalPanel panel = new VerticalPanel(); panel.add(popupButton); panel.add(dialogButton); panel.setSpacing(8); initWidget(panel); } }
GWTApplication.java
public class GWTApplication implements EntryPoint { public void onModuleLoad() { MyComponent com = new MyComponent(); RootPanel.get().add(com); } }
Также есть возможность оформить компонент в виде модуля (содержит логику и представление компонента).
Ссылки
Наследование шаблонов
Никакого наследования шаблонов. Есть текущая страница, которая строится на лету.
Литература, сообщество, применение в реальных проектах
Очень подробная документация с множеством примеров. Google использует GWT в ряде своих проектов: Google Wave, Google Moderator. Также GWT используется:
- облачным провайдером Go Grid для управления инфраструктурой серверов;
- компанией Compiere, которая перешла со Spring на GWT при переделке своей ERP системы;
- ещё в ряде проектов)
Ссылки
- Google Web Toolkit
- Hupa
- Who’s using GWT?
- Google Web Toolkit in Action
- Switching from Swing to GWT
- GoGrid
- A Preview of Google Web Toolkit 2.0
- Measure in milliseconds: Meet Speed Tracer
Итог
Как видно из примеров, где GWT реально применяется он хорош при построении сложных приложений близких к настольным. В нём действительно много клёвых вещей и в версии 2.0 сильно возросла скорость разработки (гляньте обзорное видео по GWT из предыдущего раздела). Но для полной замены JSF он, имхо, не совсем подходит. Хотя для админки был бы очень даже в тему.
Плюсы:
- наличие удобных инструментов для тестирования и отладки;
- весь код пишется на Java;
- большое количество готовых компонентов.
Минусы:
- нет нормального шаблонного движка и механизма тэгов;
- возможны проблемы с SEO.
Ссылки
Итог
Составим небольшую сравнительную табличку.
| JSF | Wicket | GWT | |
| Реализация навигации по страницам | + | +/- | - |
| Локализация | + | + | + |
| Возможность использования бинов в слое представления (web-beans) | + | +/- | +/- |
| Отображение полей сущности на поля формы | + | + | +/- |
| Конвертеры и валидаторы | + | +/- | +/- |
| Создание собственных компонентов | + | + | + |
| Наследование шаблонов | + | - | - |
| Литература, сообщество, применение в реальных проектах | + | +/- | + |
На мой взгляд при работе с существующей связкой Seam + JSF оптимальный вариант на ней и остаться, т.к. преимущества использования JSF есть и они весьма весомы (именно с точки зрения использования с Seam). На GWT можно переделать часть разделов со сложным интерфейсом. А Wicket… Переносить на него существующий проект я бы не стал, а вот новый можно попробовать “for fun”. Также за кадром осталась JSP, хотя вариант с JSP неплох за счёт высокой скорости отрисовки страниц.
Здравствуйте, тёзка.
Возможно вам будет интересно посмотреть также на технологию HybridJava.
И вот ещё – касательно Wicket критика есть здесь: http://www.theserverside.com/news/thread.tss?thread_id=54866#320116
Алекс
Здравствуйте!
Честно сказать, не понял, что вы имели в виду, когда писали в табличке, что у викета отсутствует наследование шаблонов. Оно там присутствует! И никаких костылей не нужно. Ну или если вам не нравится вставлять тег wicket:child, тогда ваше мнение понятно. Только чем wicket:child хуже ui:insert и ui:define в jsf, не совсем ясно. А так не хуже, чем в jsf, можно создавать иерархии страниц или лепить их из отдельных компонентов.
Так же в строке “Возможность использования бинов в слое представления (web-beans)” тоже непонятно что написано. Получается что викет и может и не может использовать эти бины? Взгляните тогда на сайт youeat.org. Он сделан как экспериментальный проект и исходные коды его можно найти на http://youeat.googlecode.com/svn Там честно используются бины в слое представления, никаких Dto.
Также насчет перехода по страницам – в викете все это есть и реализовывать можно совершенно по-разному, а не только через setResponsePage(…)/setRequestTarget(…). Вдобавок, если вам не хочется статические переходы прописывать в java-коде, есть тег wicket:link.
Все основано на реальных событиях.
Здравствуйте, Виктор!
Извиняюсь за запоздалый ответ. В первую очередь спасибо за критику, изучение было местами весьма поверхностным, поэтому в ряде вопросов не разобрался как следует из-за нехватки времени. В ближайшее время поправлю статью)
А над какие проектом Вы работаете? Выложен ли в Интернете? Сразу использовали Wicket или перешли с другого фреймворка? Как в плане удобства?)