2015/05/29

Vaadin Conditional bean validation with BeanFieldGroup

In this post you will get to know the following items

  • A brief introduction to FieldGroup and BeanFieldGroup in Vaadin
  • How bean validation is automatically done in BeanFieldGroup
  • The basic challenges we face when using the bean validation
  • Possible solutions to the challenges


Vaadin FieldGroup and BeanFieldGroup makes it super easy to develop data entry forms backed by a data model. You can find how to make use of this feature in the respective links listed above.

With BeanFieldGroup we can develop a data entry form backed by a bean item. In this case the data entered in the form will be stored in a POJO(Plain Old Java Object) which we provide. Support for buffering of data, discarding the changes if necessary is already provided by the FieldGroup implementation.

As the BeanFieldGroup is intended to use with a bean, it comes loaded with the facility to do Java Bean validation. The API implements the JSR-303 bean validation API. Actually the bean field group does not do magic. It just adds a validator which is a BeanValidator to every field it binds as shown below.

Person bean = new Person("Mung bean", 100);
BeanItem<Person> item = new BeanItem<Person> (bean);
    
// Create a text field bound to a bean field
TextField firstName = new TextField("First Name",
        item.getItemProperty("name"));
    
// Add the bean validator
firstName.addValidator(new BeanValidator(Person.class, "name"));
    
firstName.setImmediate(true);

So if we instead use a BeanFieldGroup it will automatically do the above to add an appropriate validator when we bind the fields as shown below
// Have a bean
Person bean = new Person("Mung bean", 100);
        
// Form for editing the bean
final BeanFieldGroup<Person> binder =
        new BeanFieldGroup<Person>(Person.class);
binder.setItemDataSource(bean);
layout.addComponent(binder.buildAndBind("Name", "name"));
layout.addComponent(binder.buildAndBind("Age", "age"));

If we render the above form, the fields will be validated against whatever the constraints that we have defined in the Person bean using validation annotations( @NotNull, @Min, @Max etc).

Overcome firing the validation when the form is first loaded

One problem is the @NotNull validations will be fired up when the form is first rendered if the respective fields are null. Sometimes we do not want to fire all the validations when an empty form is displayed for the first time, but need validations to fire only when the form is submitted. 
Usually when we add BeanValidators, Vaadin will fire up all the validations when the form fields are first rendered. This is the default behavior.
To overcome this what we can do is set the setValidationVisible(false) to initially suppress any validation errors and make them not visible. Later set this to true only when the form is first submitted.

field.setValidationVisible(false);

The above method is available in the AbstractField. So you need to cast any TextField, ComboBox or any other field component.

2015/03/09

Start Spring Transaction per request but reduce database connections

In my previous blog post, I explained how to make spring declarative transactions to behave truly transactional. We do not need to do anything special in a Spring MVC project. But if we use any other UI controller then we have to start a dummy transaction at the beginning of a HTTP request and end that transaction at the end of that request.

One concern in this method is, since it starts and end transactions per HTTP request, will it increase the number of database connections and disconnections. Well there is a possibility and it will reduce the overall performance of the system.

As described in Class DataSourceTransactionManager it is a good  idea to create a database connection when it is actually needed for example only when executing a SQL statement. In this way a dummy transaction will be started but it will not create a database connection. The connection will be established only when it is needed during the transaction.

Extract from the class documentation


"Consider defining a LazyConnectionDataSourceProxy for your target DataSource, pointing both this transaction manager and your DAOs to it. This will lead to optimized handling of "empty" transactions, i.e. of transactions without any JDBC statements executed. A LazyConnectionDataSourceProxy will not fetch an actual JDBC Connection from the target DataSource until a Statement gets executed, lazily applying the specified transaction settings to the target Connection."


So we will define LazyConnectionDataSourceProxy based on a usual datasource. Then transaction manager as well as our JdbcTemplate will be pointed to this LazyConnectionDataSource as below.
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="lazyConnectionDatasourceProxy" />
</bean>
<!-- Lazy creation of database connections-->
<bean id="lazyConnectionDatasourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="dataSource"/>
</bean>
<!-- JNDI actual datasource -->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDS" expected-type="javax.sql.DataSource"/>
<!-- Definition for JDBCTemplate bean -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="lazyConnectionDatasourceProxy" />
</bean>
view raw context.xml hosted with ❤ by GitHub

Now JdbcTemplate as well as the Transaction manager will grab a database connection only when it is actually needed.

2015/03/06

Use JDBC, Spring transactions and @Transactional

Ever wanted to use spring declarative transaction management with a different UI technology than Spring MVC and found out it does not behave really transactional?

There is a good discussion in stackoverflow Spring transaction internals. This describes how spring expects the transactions to behave. I faced a problem when using Spring declarative transactions with Vaadin UI framework which is described more detailed in stackoverflow. The issue I faced was even though I used @Transactional(propagation = Propagation.PROPAGATION_REQUIRED) in my service methods, when those methods are called from a single method in UI, spring treats each of these calls as different transactions and commits the transaction at the end of each service method. The expected behavior was if service methods, methodA(), methodB() and methodC() is called from a caller() method located in UI, those three methods to participate in a single transaction and caller operation to be an atomic operation.

After investigating the issue closely the reason was, Spring will make the methodA(), methodB() and methodC() participate in a single transaction only if a transaction is already started when calling the first service method which is annotated with @Transactional. If this requirement is not met, then the transaction proxy who calls the methodA() will create a transaction. But this transaction will end after executing methodA() and a new transaction is created by the proxy for executing the methodB() and so on. This leads to the behavior of committing after each method call.

So if we can start a transaction before the caller() method in UI kicks in, then Spring transaction proxy will make the methodA() participate in that transaction, and methodB() and methodC(). In this case lets assume if the methodC() is annotated with @Transactional and the propagation setting is PROPAGATION_REQUIRESNEW, the proxy will create a new transaction. This is the expected behavior.

So in SpringMVC and hibernate environment this is done using an OpenSessionInViewFilter which starts a hibernate session in each http request and commits or rollback that transaction at the end of that request. A similar strategy can also be used in our problem. Simply start a transaction in each request and commit or rollback it at the end of the request. This way a dummy transaction is always available when service methods are called and then Spring will nicely manage to participate, create further new transactions or not support the transactions.

A sample servlet filter I came up with is listed below
public class TransactionFilter implements Filter {
@Autowired
PlatformTransactionManager transactionManager;
TransactionDefinition transactionDefinition;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
transactionDefinition = new DefaultTransactionDefinition();
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
TransactionStatus status = transactionManager.getTransaction(transactionDefinition);
try {
filterChain.doFilter(servletRequest, servletResponse);
transactionManager.commit(status);
}catch(Throwable ex){
if(!status.isCompleted()){
transactionManager.rollback(status);
}
throw new ServletException(ex);
}
}
@Override
public void destroy() {
}
}
What this does is get the default transaction manager and starts a new transaction and commit the transaction at the end of the filter chain. As this filter uses spring transaction libraries, the filter should be registered with org.springframework.web.filter.DelegatingFilterProxy as below.
<!--Filter to create transaction per request -->
<filter>
<filter-name>transactionFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
view raw web.xml hosted with ❤ by GitHub
Then define a bean in spring context.xml that points to the filter class as below.
<bean id="transactionFilter" class="com.xyz.ui.TransactionFilter"/>
Now all set except for the fact that it creates a transaction per request as well as a database connection per request. This can be improved and it will be discussed in the next post.

EDIT: Lazy creation of database connections

2015/03/02

Use Vaadin, Apache shiro and "Remember-me"

While there are numerous solutions to use apache shiro and vaadin, Mike Pilones this solution works well except the "Remember-me" functionality. The reason for this is when using this method, we have to refrain from using a servlet filter that initializes the security manager. Thus shiro is unable to get hold of the servlet response and set the "Remember-me" cookie.

To overcome this, we have to subclass the CookieRememberMeManager and override few methods to include ServletRequest and ServletResponse to be obtained from VaadinServletService.

public class VaadinShiroRememberMeManager extends org.apache.shiro.web.mgt.CookieRememberMeManager {
@Override
protected void rememberSerializedIdentity(Subject subject, byte[] serialized) {
//base 64 encode it and store as a cookie:
String base64 = Base64.encodeToString(serialized);
Cookie template = getCookie(); //the class attribute is really a template for the outgoing cookies
Cookie cookie = new SimpleCookie(template);
cookie.setValue(base64);
cookie.saveTo(VaadinServletService.getCurrentServletRequest(),
VaadinServletService.getCurrentResponse().getHttpServletResponse());
}
@Override
protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {
String base64 = getCookie().readValue(VaadinServletService.getCurrentServletRequest(), VaadinServletService.getCurrentResponse().getHttpServletResponse());
// Browsers do not always remove cookies immediately (SHIRO-183)
// ignore cookies that are scheduled for removal
if (Cookie.DELETED_COOKIE_VALUE.equals(base64)) return null;
if (base64 != null) {
base64 = ensurePadding(base64);
byte[] decoded = Base64.decode(base64);
return decoded;
} else {
//no cookie set - new site visitor?
return null;
}
}
@Override
protected void forgetIdentity(Subject subject) {
forgetIdentity(VaadinServletService.getCurrentServletRequest(),
VaadinServletService.getCurrentResponse().getHttpServletResponse());
}
@Override
public void forgetIdentity(SubjectContext subjectContext) {
forgetIdentity(VaadinServletService.getCurrentServletRequest(),
VaadinServletService.getCurrentResponse().getHttpServletResponse());
}
private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
getCookie().removeFrom(request, response);
}
private String ensurePadding(String base64) {
int length = base64.length();
if (length % 4 != 0) {
StringBuilder sb = new StringBuilder(base64);
for (int i = 0; i < length % 4; ++i) {
sb.append('=');
}
base64 = sb.toString();
}
return base64;
}
}
Now we have to set our custom remember me manager in the shiro Security manager as follows.
<bean id="rememberMeManager" class="com.xyz.VaadinShiroRememberMeManager"/>
<bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
<property name="realms">
<list>
<ref bean="ldapRealm"/>
<ref bean="x509CertificateRealm"/>
<ref bean="jdbcAuthRealm"/>
</list>
</property>
<property name="sessionManager" ref="sessionManager"/>
<property name="authenticator.authenticationStrategy" ref="authcStrategy"/>
<!--<property name="sessionManager.sessionIdCookie.domain" value="${security.cookie.domain}"/>-->
<property name="rememberMeManager" ref="rememberMeManager"/>
<property name="rememberMeManager.cookie.name" value="Remember-me"/>
<property name="rememberMeManager.cookie.maxAge" value="500"/>
</bean>
view raw context.xml hosted with ❤ by GitHub

Now shiro security manager can set and retrieve any remember-me cookie using the VaadinServletService provided request and response objects.