Directory

← Back

JDAL Vaadin UI Library

Spring integration, form data binding and UI component library

Author

Rating

Popularity

<100

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>

Compatibility

(Loading compatibility data...)

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

Released
2012-06-01
Maturity
BETA
License
Apache License 2.0

Compatibility

Framework
Vaadin 6.0+
Vaadin 7.0+ in 2.0.M1
Browser
Internet Explorer
Internet Explorer
Internet Explorer
Firefox
Opera
Safari
Google Chrome
Internet Explorer

Vaadin Add-on Directory

Find open-source widgets, add-ons, themes, and integrations for your Vaadin application. Vaadin Add-on Directory
The channel for finding, promoting, and distributing Vaadin add-ons.
Online