You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Carlos Cajina <ce...@hotmail.com> on 2004/11/18 17:27:36 UTC

[BEAN UTILS] mini HOW-TO for dummies

Hi. After day and a half struggling to grasp the use of commons-beanutils regarding (automatic) data type conversions I finally came up with what I'd like to think of as a good starting point for those who -like me- start from zero. Before diving into code examples I'd like to share what made me look into commons-beanutils for a solution:

* Since I'm using Struts in my current J2EE project one of my concerns was to find a way to transfer data between the presentation layer and the data layer. From the Struts part I have ActionForms and from the data persistence part I have Value Objects and CMP Entity Beans.

* According to Ted Husted's "Struts in Action" (2003, Manning) there are several strategies to transfer values between tiers. I was using one that relies on "factory methods" ("A helper method encapsulates, instantiates, and populates a business tier bean."), but including such methods in my ActionForms to instantiate, populate, and return a specific value object brought along (at least to me) messy code to handle data type conversions and validations, moreover, as Ted points it "This strategy binds the ActionForm to the business-tier type". Of course there are advantages to this approach, but the use of reflection -as I hope you'll see- is a cleaner and safer path, and introduces very little overhead.

* For the sake of simplicity in my ActionForms I only have string properties -even though users "see" and save String, Date, Integer, Boolean, Timestamp, and Float values. Considering that the BeanUtils methods can convert data between Strings and native types this seemed like a good decision. If you have "exotic" data types,s you'll have to implement "bridge methods" to keep data type conversion transparent (I'll show a rather simple example later)

Having described some of my scenario, here's what I did:

1. Following commons-beanutils JavaDocs' two-step recipe, I wrote a class that implemented the Converter interface. Within this class the convert() method should accept theclass that you want to convert to, and a String representing the incoming value to be converted. I had to go through this first step because from the user perspective dates are handled in dd-mm-yyyy format but they go into the database as an SQL DATE value, using yyyy-mm-dd format. To implement the Converter interface I kind of cheated because I grabbed commons-beanutils source code and peek into the default SqlDateConverter class code (written by Mr. Craig R. McClanahan) What I did next was re-implement the convert() method to add code within the try to "reverse" the date format, like this:

int year,month,day;
String userDate = (String) value;
            
year = Integer.parseInt(userDate.substring(6));
month = Integer.parseInt(userDate.substring(3,5));
day = Integer.parseInt(userDate.substring(0,2));
            
GregorianCalendar dbDate = new GregorianCalendar(year, month-1, day);
                        
Date correctDate = new Date(dbDate.getTimeInMillis());
            
return (correctDate);

NOTE: there are default converters that use Locale objects, if you need something more refined.

2. The next step in the recipe is to "register an instance of your converter class by calling the ConvertUtils.register() method". It is suggested that this be done at application startup time, and since I already had a ServletContext Listener I just added the following lines in the contextInitialized method:

appContext.log("Registering MyOwnSqlDateConverter..."); 
ConvertUtils.register(new MyOwnSqlDateConverter(),java.sql.Date.class);
appContext.log("MyOwnSqlDateConverter registered...");

As you can imagine, for every String to java.sql.Date conversion that takes place in the application the converter to use will be the one I'm providing in step 1 and registering in step 2.

3. Finally, to populate ActionForms and create Value Objects you should add some simple methods:

    public void populateFormFromValueObjectData(Object vo) throws Exception
    {
        try {
            BeanUtils.copyProperties(this, vo);
        } catch (Throwable t) {
            throw new PopulateSolicitudDataException(t);
        }
    }

and

    public SomeValueObject getSomeValueObjectFromFormData() throws Exception
    {
        SomeValueObject svo = new SomeValueObject();

        try {
            BeanUtils.copyProperties(svo, this);
        } catch (Throwable t) {
            throw new PopulateSolicitudVOException(t);
        }

        return svo;
    }

In both cases, "this" references the ActionForm. In the first method, BeanUtils.copyProperties(this, vo) copy property values from the origin bean (vo) to the destination bean (this=ActionForm) for all cases where the property names are the same, doing all the necessary data type conversions under the hood; and the same applies for BeanUtils.copyProperties(svo, this).

Doing things this ways allows you to transfer data between tiers without binding your form to the business tier, in fact, you don't even have to know the details of the data transfer objects (value objects) to get data from them and send data through them. Mr. Husted refers to this kind of felxibility as "round-tripping ActionForms and business beans".

One of my actual ActionForms has to gather a lot of data (or is it datum? sorry, not very good in english grammar) using wizard like screens, but this information doesn't go to the same places in the database. I create three different types of Value Objects and obtain information from those three types with just a few lines of code and without caring about any data type conversions. This is one step closer to heaven for me! :^)

I hope this serves you as a good and practical introduction to part of the commons-beanutils power ;^)  If any questions arise or you come up with better examples and/or corrections, please share them!

Regards,

    Carlos

Re: [BEAN UTILS] mini HOW-TO for dummies

Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
hi carlos

thanks for taking time to post the mini HOW-TO. any chance that you 
could add an edited and formatted version to the wiki 
(http://wiki.apache.org/jakarta-commons/)?

(that way, people will be able to find it more easily in the future.)

- robert

On 18 Nov 2004, at 16:27, Carlos Cajina wrote:

> Hi. After day and a half struggling to grasp the use of 
> commons-beanutils regarding (automatic) data type conversions I 
> finally came up with what I'd like to think of as a good starting 
> point for those who -like me- start from zero. Before diving into code 
> examples I'd like to share what made me look into commons-beanutils 
> for a solution:
>
> * Since I'm using Struts in my current J2EE project one of my concerns 
> was to find a way to transfer data between the presentation layer and 
> the data layer. From the Struts part I have ActionForms and from the 
> data persistence part I have Value Objects and CMP Entity Beans.
>
> * According to Ted Husted's "Struts in Action" (2003, Manning) there 
> are several strategies to transfer values between tiers. I was using 
> one that relies on "factory methods" ("A helper method encapsulates, 
> instantiates, and populates a business tier bean."), but including 
> such methods in my ActionForms to instantiate, populate, and return a 
> specific value object brought along (at least to me) messy code to 
> handle data type conversions and validations, moreover, as Ted points 
> it "This strategy binds the ActionForm to the business-tier type". Of 
> course there are advantages to this approach, but the use of 
> reflection -as I hope you'll see- is a cleaner and safer path, and 
> introduces very little overhead.
>
> * For the sake of simplicity in my ActionForms I only have string 
> properties -even though users "see" and save String, Date, Integer, 
> Boolean, Timestamp, and Float values. Considering that the BeanUtils 
> methods can convert data between Strings and native types this seemed 
> like a good decision. If you have "exotic" data types,s you'll have to 
> implement "bridge methods" to keep data type conversion transparent 
> (I'll show a rather simple example later)
>
> Having described some of my scenario, here's what I did:
>
> 1. Following commons-beanutils JavaDocs' two-step recipe, I wrote a 
> class that implemented the Converter interface. Within this class the 
> convert() method should accept theclass that you want to convert to, 
> and a String representing the incoming value to be converted. I had to 
> go through this first step because from the user perspective dates are 
> handled in dd-mm-yyyy format but they go into the database as an SQL 
> DATE value, using yyyy-mm-dd format. To implement the Converter 
> interface I kind of cheated because I grabbed commons-beanutils source 
> code and peek into the default SqlDateConverter class code (written by 
> Mr. Craig R. McClanahan) What I did next was re-implement the 
> convert() method to add code within the try to "reverse" the date 
> format, like this:
>
> int year,month,day;
> String userDate = (String) value;
>
> year = Integer.parseInt(userDate.substring(6));
> month = Integer.parseInt(userDate.substring(3,5));
> day = Integer.parseInt(userDate.substring(0,2));
>
> GregorianCalendar dbDate = new GregorianCalendar(year, month-1, day);
>
> Date correctDate = new Date(dbDate.getTimeInMillis());
>
> return (correctDate);
>
> NOTE: there are default converters that use Locale objects, if you 
> need something more refined.
>
> 2. The next step in the recipe is to "register an instance of your 
> converter class by calling the ConvertUtils.register() method". It is 
> suggested that this be done at application startup time, and since I 
> already had a ServletContext Listener I just added the following lines 
> in the contextInitialized method:
>
> appContext.log("Registering MyOwnSqlDateConverter...");
> ConvertUtils.register(new MyOwnSqlDateConverter(),java.sql.Date.class);
> appContext.log("MyOwnSqlDateConverter registered...");
>
> As you can imagine, for every String to java.sql.Date conversion that 
> takes place in the application the converter to use will be the one 
> I'm providing in step 1 and registering in step 2.
>
> 3. Finally, to populate ActionForms and create Value Objects you 
> should add some simple methods:
>
>     public void populateFormFromValueObjectData(Object vo) throws 
> Exception
>     {
>         try {
>             BeanUtils.copyProperties(this, vo);
>         } catch (Throwable t) {
>             throw new PopulateSolicitudDataException(t);
>         }
>     }
>
> and
>
>     public SomeValueObject getSomeValueObjectFromFormData() throws 
> Exception
>     {
>         SomeValueObject svo = new SomeValueObject();
>
>         try {
>             BeanUtils.copyProperties(svo, this);
>         } catch (Throwable t) {
>             throw new PopulateSolicitudVOException(t);
>         }
>
>         return svo;
>     }
>
> In both cases, "this" references the ActionForm. In the first method, 
> BeanUtils.copyProperties(this, vo) copy property values from the 
> origin bean (vo) to the destination bean (this=ActionForm) for all 
> cases where the property names are the same, doing all the necessary 
> data type conversions under the hood; and the same applies for 
> BeanUtils.copyProperties(svo, this).
>
> Doing things this ways allows you to transfer data between tiers 
> without binding your form to the business tier, in fact, you don't 
> even have to know the details of the data transfer objects (value 
> objects) to get data from them and send data through them. Mr. Husted 
> refers to this kind of felxibility as "round-tripping ActionForms and 
> business beans".
>
> One of my actual ActionForms has to gather a lot of data (or is it 
> datum? sorry, not very good in english grammar) using wizard like 
> screens, but this information doesn't go to the same places in the 
> database. I create three different types of Value Objects and obtain 
> information from those three types with just a few lines of code and 
> without caring about any data type conversions. This is one step 
> closer to heaven for me! :^)
>
> I hope this serves you as a good and practical introduction to part of 
> the commons-beanutils power ;^)  If any questions arise or you come up 
> with better examples and/or corrections, please share them!
>
> Regards,
>
>     Carlos


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org