Saturday, March 19, 2011

How to configure the way BeanUtils converts null value

By default BeanUtils.setProperty always assign a default value for null. For an instance, if the property's type being set is Integer then you will get 0. This could be the behavior that many do not expect, for example you use Struts and you have an entry form with a number field. And you're expecting that if the user leave it empty, you would like to display it as empty later on.
BeanUtils utilized by Struts will fill the field as 0 instead of leaving it null.

Underneath BeanUtils is utilizing a ConverterUtils to convert the value before setting it to the property. Therefore to change this behavior all we need to do is to register a new IntegerConverter to ConverterUtils, thereby overriding the default converter used.

e.g.
ConvertUtils.register(new IntegerConverter(null), Integer.class);

The same thing you should do for other types as needed.

If you indeed configure the converter, you might want to read this.

Tuesday, March 15, 2011

Understanding seam's persistence context configuration

Actually this post is a note for myself regarding how seam could be configured in the web application. The facts are:
- The application is running on JBoss 5.1
- Seam is used to manage the lifecycle of EntityManager instances

Here's the configuration:
  1. Datasource configuration file placed in {server}/deploy
    JNDI name is Datasource
  2. Persistence unit configuration in persistence.xml
    <persistence-unit name="PersistenceUnit" transaction-type="JTA">
    <provider
    >org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>Datasource</jta-data-source>
    ......
    <properties
    >
    ........
    <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactory"/>
    </properties>


  3. Declaration of persistence-unit-ref element in web.xml
    <persistence-unit-ref>
    <persistence-unit-ref-name>PersistenceUnit/pu</persistence-unit-ref-name>
    <persistence-unit-name>PersistenceUnit</persistence-unit-name>
    </persistence-unit-ref>

  4. Configuration in component.properties
    seamBootstrapsPu=false
    seamEmfRef=#{null}
    puJndiName=java:comp/env/PersistenceUnit/pu
  5. Configuration of persistence managed context in components.xml
    <persistence:managed-persistence-context name="entityManager" auto-create="true"
    entity-manager-factory="@seamEmfRef@"
    persistence-unit-jndi-name="@puJndiName@"/>


Here's the short explanation:
  1. A new datasource is deployed (step 1)
  2. The datasource is referred to in persistence.xml (step 2)
  3. Add reference to the new persistence unit name in web.xml (step 3)
  4. Add new property in component.properties which refers to the persistence-unit-ref-name declared in web.xml (step 4)
  5. The values configured in component.properties is used to configure the managed-persistence-context (step 5)

Note: The entity manager factory is bound to the global JNDI thru "jboss.entity.manager.factory.jndi.name" property configured during step 2, however it is not used... yet :)

Thursday, March 10, 2011

Beware of customizing BeanUtils converter

If you ever have to customize BeanUtils converter just like I did, one thing that should be of your concern and that is BeanUtils is also utilized by many open source libraries. And some of the libraries might happened to have the same need as yours to customize the converters. If in any case you are using one of those libraries, it just might override your converters.

In my case, I was using jXLS . It is a great tool and it's my fault that I didn't read the documentation thoroughly. The documentation says:

"jXLS integrates with Jakarta BeanUtils conversion utilities to perform actual conversion from Excel cell values into bean properties...... BeanUtils Converters for primitive types return a default value when a conversion error occurs. jXLS overrides this behaviour in ReaderConfig class registering these classes to throw a ConversionException."

And what I configured for my application is for BeanUtils to return null for empty string instead of the default value.

Now, here's a short story on what truly happened to my application due to the conflict described above:
At first, an empty text field (for number input) in the form is converted to null and after some operations performed on the application "suddenly" it throws NumberFormatException for empty text field in the form. I'm lucky to know the steps to reproduce it and it turns out that things started to act strange after jXLS is utilized (to create/read excel file).

At this point, I'm grateful to have jXLS and BeanUtils source code. I could just debug into the source code and analyze it. And I found out that jXLS overrides BeanUtils's converter configuration as the documentation said. Now all I can do is after every invocation of jXLS I have to reconfigure BeanUtils as my application need it.

One more thing still disturb me, how to handle concurrent processes where one process is still working on jXLS and the other one need to convert the value from the form. And both are utilizing BeanUtils. I guessed at this moment I have to accept that I will get NumberFormatException and tell the user to try to submit the form again (and hoping that the jXLS process is already finished).