JDAL Vaadin UI Library
Spring integration, form data binding and UI component library
JDAL Vaadin is a port of JDAL Swing Library to Vaadin including the following features:
Spring Integration:
- Spring custom namespace for configuring Vaadin components in bean definiton files.
- Serializable proxy support to allow injecting spring beans into Vaadin components with session pasitivation and replication across cluster nodes.
- Spring scope for Vaadin 7 UIs.
- Resource property editor to allow injecting resources in bean definition files.
- Spring UIProvider.
- Spring Security integration
- ListBeanContainer with support of indexed properties, ie person.addresses[0]
UI Library:
- Automatic and annotation driven form data binding between views and models.
- Support for JSR-303 and spring validators.
- Server side paged table with navigation and filtering support.
- Form building support class.
- Configurable login form
- Configurable button bar for Vaadin navigator.
And more...
Sample code
<!-- Book Table Definition --> <vaadin:table entity="org.jdal.samples.model.Book" filter-form="bookFilterEditor" scope="prototype"> <vaadin:columns> <vaadin:column name="id" display-name="ID" width="60" align="center"/> <vaadin:column name="name" display-name="Name" width="300" align="left" /> <vaadin:column name="author" display-name="Author" width="150" align="left" sort-property-name="author.name" /> <vaadin:column name="category" display-name="Category" width="200" align="left" sort-property-name="category.name" /> <vaadin:column name="isbn" display-name="ISBN" width="150" align="left" /> <vaadin:column name="publishedDate" display-name="Published Date" width="150" property-editor="customDateEditor"/> </vaadin:columns> </vaadin:table>
<!-- Top button menu --> <vaadin:button-bar id="buttonBar" scope="prototype"> <vaadin:actions> <vaadin:navigator-action caption="Books" view-name="bookMainView" icon="classpath:/org/freedesktop/tango/22x22/mimetypes/x-office-address-book.png"/> <vaadin:navigator-action caption="Authors" view-name="authorMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/preferences-desktop-theme.png"/> <vaadin:navigator-action caption="Categories" view-name="categoryMainView" icon="classpath:/org/freedesktop/tango/22x22/places/folder.png" /> <vaadin:navigator-action caption="Users" view-name="userMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/system-users.png"/> <vaadin:navigator-action caption="About" view-name="aboutMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/help-browser.png"/> <bean class="org.jdal.vaadin.ui.action.ExitAction" p:caption="Exit" p:icon="classpath:/org/freedesktop/tango/22x22/actions/system-shutdown.png" /> </vaadin:actions> </vaadin:button-bar> <!-- Make main views ui scoped to avoid recreating thems in every page change --> <bean id="bookMainView" class="org.jdal.samples.vaadin.BookMainView" scope="ui" /> <bean id="authorMainView" class="org.jdal.samples.vaadin.AuthorMainView" scope="ui" /> <bean id="categoryMainView" class="org.jdal.samples.vaadin.CategoryMainView" scope="ui" /> <bean id="aboutMainView" class="org.jdal.samples.vaadin.AboutMainView" scope="ui" /> <bean id="userMainView" class="org.jdal.samples.vaadin.UserMainView" scope="ui" />
public class BookView extends AbstractView<Book> { private TextField name = new TextField(); private TextField isbn = new TextField(); private DateField publishedDate = new DateField(); @Initializer(orderBy="name") private ComboBox author = new ComboBox(); @Initializer(orderBy="name") private ComboBox category = new ComboBox(); public BookView() { this(new Book()); } public BookView(Book model) { super(model); } @PostConstruct public void init() { autobind(); } @Override protected Component buildPanel() { BoxFormBuilder fb = new BoxFormBuilder(); fb.setDefaultWidth(SimpleBoxFormBuilder.SIZE_FULL); fb.setFixedHeight(); fb.row(); fb.add(name, getMessage("Book.title")); fb.row(); fb.startBox(); fb.row(); fb.add(author, getMessage("Book.author")); fb.add(category, getMessage("Book.category")); fb.endBox(); fb.row(); fb.startBox(); fb.row(); fb.add(isbn, getMessage("Book.isbn")); fb.add(publishedDate, getMessage("Book.publishedDate"), 120); fb.endBox(); return fb.getForm(); } }
@Entity @Table(name="books") public class Book implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; @NotEmpty private String name = ""; @NotNull @ManyToOne @JoinColumn(name="authorid") private Author author; @NotNull @ManyToOne @JoinColumn(name="categoryid") private Category category; private String isbn = ""; private Date publishedDate; // Getters and setters }
Book.title = Title Book.category = Category Book.author = Author Book.publishedDate = Published Date Book.isbn = ISBN BookFilter.publishedBefore = Before BookFilter.publishedAfter = After #Error Messages NotNull.Book.category= The category is required. NotEmpty.Book.name = The title is required. NotNull.Book.author = The autor is required. NotEmpty.Category.name = The category name is required. NotEmpty.Author.name = The author name is required. NotEmtpy.Author.surname = The author surname is required.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" default-init-method="init" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:vaadin="http://www.jdal.org/schema/vaadin" xmlns:jdal="http://www.jdal.org/schema/jdal" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="http://www.jdal.org/schema/jdal http://www.jdal.org/schema/jdal/jdal-core.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd http://www.jdal.org/schema/vaadin http://www.jdal.org/schema/jdal/jdal-vaadin.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config/> <import resource="context/dao-context.xml"/> <import resource="context/view-context.xml" /> <!-- Enable @SerializableProxy support --> <bean id="serializableAnnotationBeanPostProcessor" class="org.jdal.aop.config.SerializableAnnotationBeanPostProcessor" /> <bean id="serializableProxyAdvisor" class="org.jdal.aop.SerializableProxyAdvisor" scope="prototype"/> <!-- Message Source --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames" value="i18n/jdal,i18n/i18n" /> <!-- Repalace with serializable proxy --> <jdal:serializable-proxy/> </bean> <!-- Needed for jdal library, don't delete --> <bean id="staticMessageSource" class="org.jdal.beans.StaticMessageSource"> <constructor-arg ref="messageSource" /> </bean> </beans>
<!-- UI Widgets --> <!-- Register default Vaadin components --> <vaadin:defaults /> <!-- Vaadin scoped beans are linked to UI class instances, Use with care, is still a beta component. --> <bean id="vaadinScopeConfigurer" class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="ui" value="org.jdal.vaadin.beans.VaadinScope" /> </map> </property> </bean> <!-- Application UI --> <bean id="uid" class="org.jdal.samples.vaadin.TestApp" scope="prototype" p:buttonBar-ref="buttonBar"/> <bean id="springViewProvider" class="org.jdal.vaadin.ui.SpringViewProvider" scope="prototype" p:defaultView="bookMainView" /> <!-- Top button menu --> <vaadin:button-bar id="buttonBar" scope="prototype"> <vaadin:actions> <vaadin:navigator-action caption="Books" view-name="bookMainView" icon="classpath:/org/freedesktop/tango/22x22/mimetypes/x-office-address-book.png"/> <vaadin:navigator-action caption="Authors" view-name="authorMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/preferences-desktop-theme.png"/> <vaadin:navigator-action caption="Categories" view-name="categoryMainView" icon="classpath:/org/freedesktop/tango/22x22/places/folder.png" /> <vaadin:navigator-action caption="Users" view-name="userMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/system-users.png"/> <vaadin:navigator-action caption="About" view-name="aboutMainView" icon="classpath:/org/freedesktop/tango/22x22/apps/help-browser.png"/> <bean class="org.jdal.vaadin.ui.action.ExitAction" p:caption="Exit" p:icon="classpath:/org/freedesktop/tango/22x22/actions/system-shutdown.png" /> </vaadin:actions> </vaadin:button-bar> <!-- Make main views ui scoped to avoid recreating thems in every page change --> <bean id="bookMainView" class="org.jdal.samples.vaadin.BookMainView" scope="ui" /> <bean id="authorMainView" class="org.jdal.samples.vaadin.AuthorMainView" scope="ui" /> <bean id="categoryMainView" class="org.jdal.samples.vaadin.CategoryMainView" scope="ui" /> <bean id="aboutMainView" class="org.jdal.samples.vaadin.AboutMainView" scope="ui" /> <bean id="userMainView" class="org.jdal.samples.vaadin.UserMainView" scope="ui" /> <!-- Abstract definition for Views --> <bean id="view" abstract="true"> <property name="controlInitializer" ref="controlInitializer"/> <property name="errorProcessors"> <list> <ref bean="errorProcessor" /> </list> </property> <property name="validator" ref="validator" /> </bean> <bean id="loginView" class="org.jdal.vaadin.auth.LoginView" parent="view" scope="prototype" p:width="400" p:height="250" p:applicationName="bookLibrary" p:applicationIcon="images/jdal-logo.png"/> <bean id="controlInitializer" class="org.jdal.vaadin.ui.bind.VaadinControlInitializer"> <property name="persistentService" ref="contextPersistentService" /> </bean> <!-- Spring JSR-303 validator --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <jdal:serializable-proxy /> </bean> <!-- Error Processor --> <bean id="errorProcessor" class="org.jdal.vaadin.ui.bind.UserErrorProcessor" /> <!-- Book Table Definition --> <vaadin:table entity="org.jdal.samples.model.Book" filter-form="bookFilterEditor" scope="prototype"> <vaadin:columns> <vaadin:column name="id" display-name="ID" width="60" align="center"/> <vaadin:column name="name" display-name="Name" align="left" /> <vaadin:column name="author" display-name="Author" width="150" align="left" sort-property-name="author.name" /> <vaadin:column name="category" display-name="Category" width="200" align="left" sort-property-name="category.name" /> <vaadin:column name="isbn" display-name="ISBN" width="150" align="left" /> <vaadin:column name="publishedDate" display-name="Published Date" width="150" property-editor="customDateEditor"/> </vaadin:columns> </vaadin:table> <bean id="customDateEditor" class="org.springframework.beans.propertyeditors.CustomDateEditor" scope="prototype"> <constructor-arg> <bean class="java.text.SimpleDateFormat"> <constructor-arg value="MM/dd/yyyy" /> </bean> </constructor-arg> <constructor-arg value="true" /> <jdal:serializable-proxy/> </bean> <!-- Book Form Editor --> <bean id="bookEditor" class="org.jdal.samples.vaadin.BookView" parent="view" scope="prototype" > <property name="width" value="600" /> <property name="height" value="300" /> <property name="persistentService" ref="bookService" /> </bean> <!-- View Dialog Prototype --> <bean id="viewDialog" class="org.jdal.vaadin.ui.form.ViewDialog" scope="prototype"/> <!-- The book Filter Editor --> <bean id="bookFilterEditor" class="org.jdal.samples.vaadin.BookFilterView" scope="prototype"> <property name="controlInitializer" ref="controlInitializer" /> </bean> <!-- Author Table --> <vaadin:table entity="org.jdal.samples.model.Author" filter-form="authorFilterView" scope="prototype"> <vaadin:columns> <vaadin:column name="id" display-name="ID" width="60" /> <vaadin:column name="name" display-name="Name"/> <vaadin:column name="surname" display-name="Surname" /> </vaadin:columns> </vaadin:table> <bean id="authorEditor" class="org.jdal.samples.vaadin.AuthorView" parent="view" scope="prototype" p:width="400" p:height="250" p:persistentService-ref="authorService" /> <bean id="authorFilterView" class="org.jdal.samples.vaadin.AuthorFilterView" scope="prototype" parent="view" /> <!-- Category Table --> <vaadin:table entity="org.jdal.samples.model.Category" filter-form="categoryFilterView" scope="prototype" > <vaadin:columns> <vaadin:column name="id" display-name="ID" width="60" /> <vaadin:column name="name" display-name="Name" /> </vaadin:columns> </vaadin:table> <bean id="categoryEditor" class="org.jdal.samples.vaadin.CategoryView" parent="view" scope="prototype" p:width="400" p:height="250" p:persistentService-ref="categoryService" /> <bean id="categoryFilterView" class="org.jdal.samples.vaadin.CategoryFilterView" scope="prototype" /> <!-- User Table --> <vaadin:table entity="org.jdal.samples.model.User" filter-form="userFilterView" scope="prototype"> <vaadin:columns> <vaadin:column name="id" display-name="ID" width="60" /> <vaadin:column name="username" display-name="User" width="120"/> <vaadin:column name="name" display-name="Name" /> <vaadin:column name="surname" display-name="Surname" /> <vaadin:column name="registerDate" display-name="Register Date" width="100" /> <vaadin:column name="email" display-name="Email" width="120" /> </vaadin:columns> </vaadin:table> <bean id="userEditor" class="org.jdal.samples.vaadin.UserView" parent="view" scope="prototype" p:width="500" p:height="300" p:persistentService-ref="userService" /> <bean id="userFilterView" class="org.jdal.samples.vaadin.UserFilterView" parent="view" scope="prototype" /> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdal="http://www.jdal.org/schema/jdal" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" default-init-method="init" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.jdal.org/schema/jdal http://www.jdal.org/schema/jdal/jdal-core.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:property-placeholder location="classpath:jdbc.properties"/> <jdbc:embedded-database id="dataSource" type="H2"> <jdbc:script location="classpath:create.sql"/> <jdbc:script location="classpath:import.sql"/> </jdbc:embedded-database> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan" value="org.jdal.samples.model" /> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/> </property> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/> </bean> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="dataSource" ref="dataSource"/> </bean> <!-- DAOs --> <jdal:service entity="org.jdal.samples.model.Category"> <jdal:criteria name="categoryFilter" builder="categoryCriteriaBuilder" /> </jdal:service> <bean id="categoryCriteriaBuilder" class="org.jdal.samples.dao.jpa.CategoryCriteriaBuilder" /> <jdal:service entity="org.jdal.samples.model.Author"> <jdal:criteria name="authorFilter" builder="authorCriteriaBuilder" /> </jdal:service> <bean id="authorCriteriaBuilder" class="org.jdal.samples.dao.jpa.AuthorCriteriaBuilder" /> <jdal:service entity="org.jdal.samples.model.Book"> <jdal:criteria name="book" builder="bookCriteriaBuilder"/> </jdal:service> <bean id="bookCriteriaBuilder" class="org.jdal.samples.dao.jpa.BookCriteriaBuilder"/> <jdal:service entity="org.jdal.samples.model.User" dao-class="org.jdal.samples.dao.jpa.UserJpaDao"> <jdal:criteria name="userFilter" builder="userCriteriaBuilder" /> </jdal:service> <bean id="userCriteriaBuilder" class="org.jdal.samples.dao.jpa.UserCriteriaBuilder" /> <bean id="contextPersistentService" class="org.jdal.logic.ContextPersistentManager" /> <bean id="authService" class="org.jdal.auth.AuthManager"> <property name="userDao" ref="userDao" /> <property name="authStrategy" ref="authMd5" /> </bean> <bean id="authMd5" class="org.jdal.auth.AuthHashMD5" /> <!-- Tx Advice --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- the transactional semantics... --> <tx:attributes> <!-- all methods starting with 'get' and 'load' are read-only --> <tx:method name="get*" read-only="true"/> <tx:method name="load*" read-only="true"/> <!-- other methods use the default transaction settings --> <tx:method name="*"/> </tx:attributes> </tx:advice> <aop:config> <!-- Make all methods on Dao transactional --> <aop:pointcut id="txOperation" expression="execution(* org.jdal.dao.Dao.*(..)) or execution(* org.jdal.samples.dao.*.*(..)) or execution(* org.jdal.auth.AuthService.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="txOperation"/> </aop:config> <beans profile="mysql"> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClassName}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="acquireIncrement" value="3" /> <property name="minPoolSize" value="3" /> <property name="maxPoolSize" value="10" /> <property name="maxIdleTime" value="5" /> <property name="numHelperThreads" value="5" /> <property name="idleConnectionTestPeriod" value="10" /> <property name="autoCommitOnClose" value="false" /> <property name="preferredTestQuery" value="select 1;" /> <property name="testConnectionOnCheckin" value="true" /> <property name="checkoutTimeout" value="60000" /> </bean> </beans> </beans>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Vaadin Web Application</display-name> <context-param> <description>Vaadin production mode</description> <param-name>productionMode</param-name> <param-value>false</param-value> </context-param> <context-param> <description>Vaadin application class to start</description> <param-name>UIProvider</param-name> <param-value>org.jdal.vaadin.SpringUIProvider</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <!-- Spring config --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>Vaadin Application Servlet</servlet-name> <servlet-class>com.vaadin.server.VaadinServlet</servlet-class> <init-param> <param-name>UI</param-name> <param-value>org.jdal.samples.vaadin.TestApp</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Vaadin Application Servlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
Links
- Issue Tracker
- Source Code
- Discussion Forum
- Online Demo
- Release Notes
- Reference Documentation
- Author Homepage
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
- Add initial support for Spring Security.
- Add a new ListBeanContainer with support for indexed properties, ie person.addresses[0].
- New @UiMapping annotation for mapping urls to UIs.
- New @ViewConfig annoation for configurig url mapping and access for Views.
- New attribute access in <vaadin:navigator-action > tag to set access role of the buttons in button bar.
- Add Role editor to samples.
- Released
- 2015-05-13
- Maturity
- STABLE
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 7.0+
- Vaadin 6.0+ in 1.2.0
- Browser
- Internet Explorer
- Internet Explorer
- Internet Explorer
- Firefox
- Opera
- Safari
- Google Chrome
- Internet Explorer
JDAL Vaadin UI Library - Vaadin Add-on Directory
Spring integration, form data binding and UI component librarySource Code
Discussion Forum
Online Demo
Release Notes
Reference Documentation
Author Homepage
JDAL Vaadin UI Library version 1.1.0
null
JDAL Vaadin UI Library version 1.1.1
Added record count info
JDAL Vaadin UI Library version 1.1.3
- Add TableButtonListeners (Actions) for PageableTable
- Add AnnotationFieldFactory: Parse JPA annotatios when creating filelds
- Add CellEditor, CellRenderer and PropertyEditor to ConfigurableTable column definition
JDAL Vaadin UI Library version 1.1.4.PRE
This is a maintenance release and includes bug fixes and minor improvements. It should be a drop-in replacement for overlays built against 1.1.3
JDAL Vaadin UI Library version 1.2.0
null
JDAL Vaadin UI Library version 2.0.M1
- Vaadin 7 Support.
- Spring framework custom namespace for Vaadin.
- Support form validation with JSR-303 annotations.
- JDAL BoxFormBuilder has been ported to Vaadin framework.
- JDAL automatic binding between forms and models is now available for Vaadin.
JDAL Vaadin UI Library version 2.0.RC1
- Support session pasitivation via spring serializable proxies in autowired fields.
- New @SerializableProxy annotation for fields and types.
- New @Property and @Initializer annotations for data binding configuration
- New Login form.
- New navigator button bar.
- Fix Spring UI Scope.
- Fix intenationalization issues.
- Upgrade sampes
JDAL Vaadin UI Library version 2.0.0
First stable release of version 2.0
JDAL Vaadin UI Library version 2.1-RC1
- Add initial support for Spring Security.
- Add a new ListBeanContainer with support for indexed properties, ie person.addresses[0].
- New @UiMapping annotation for mapping urls to UIs.
- New @ViewConfig annoation for configurig url mapping and access for Views.
- New attribute access in