ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Using the Jakarta Commons, Part 3

by Vikram Goyal
07/23/2003

Jakarta Commons is a Jakarta subproject that creates and maintains independent packages unrelated to any other framework or product. The packages are a collection of components that serve small, useful purposes in their own right, and are usually server-centric.

The first installment of this series divided these components into five categories and described the Web and Trivial categories. The second article covered the XML and Packages categories. This article describes the final category, Utilities. Note that these categorizations are purely for organizational reasons.

Utilities

The Utilities category contains the BeanUtils, Logging, DBCP, Pool, and Validator components.

BeanUtils

Summary: Provides utilities for working with dynamic JavaBeans.

Where: Main Page, Binaries, Source.

Source Code:

Download the source code for the example application. This .zip file contains:
AppLayer1Bean.java
AppLayer2Bean.java
BeanUtilsDemo.java
SubBean.java
DBCPDemo.java
commons-logging.properties
LoggingDemo.java
MyObjectFactory.java
PoolDemo.java
MyFormBean.java
MyValidator.java
validator.xml
ValidatorDemo.java

When: When your application requires dynamic access to JavaBeans without any knowledge of pre-compiled accessors and modifiers. The JavaBeans must conform to the naming design patterns in the JavaBeans specification.

Example Applications: BeanUtilsDemo.java, AppLayer1Bean.java, AppLayer2Bean.java, SubBean.java require commons-beanutils.jar, commons-logging.jar, and commons-collections.jar in the CLASSPATH.

Description:

In dynamic Java application development environments, it is not always possible to know ahead in time about the various getter and setter methods for your JavaBeans. Even when you might know the names of the methods, you may find it cumbersome to write a setXXX or getXXX method to set or get each and every property of a bean. Consider the case of almost identical beans being transferred from one application layer to another. Do you call bean1.setXXX(bean2.getXXX()) for each and every property? You could, but you don't have to. BeanUtils does it for you! BeanUtils helps the developer with dynamic JavaBean creation, modification, and copying.

BeanUtils can act on JavaBeans that satisfy the following conditions:

  • The JavaBean must provide a no args constructor.
  • The JavaBean properties must be accessible and modifiable by getXXX and setXXX methods. For Boolean properties, isXXX and setXXX are allowed. These properties can be read/write only, which means that only get or only set for a property is allowed, too.
  • If you do decide to name your accessors and modifiers something other than the traditional "get" and "set," you must declare this in the BeanInfo class associated with your JavaBean.

Let us start with a simple example.

To get and set simple properties, use the PropertyUtils.getSimpleProperty(Object bean, String name) and PropertyUtils.setSimpleProperty(Object bean, String name, Object value) methods, respectively, as shown below with the help of AppLayer1Bean.java and AppLayer2Bean.java as our test JavaBeans.

PropertyUtils.setSimpleProperty(app1Bean, "intProp1", 
    new Integer(10));
System.err.println("App1LayerBean, stringProp1: " +
    PropertyUtils.getSimpleProperty(app1Bean, "stringProp1")); 

Why would you use these methods, when you could just as simply get (and set) the values of these beans by calling the methods directly on the beans (app1Bean.getStringProp1() or app1Bean.setIntProp1(10))? You may not always know the names of these properties in advance in your code, and therefore may not know the right methods to call. These property names might come from variables set by another process or an external application. So, for example, if you accessed the name of the property of a bean and stored it in a variable, you could pass the variable name to PropertyUtils. This reduces a dependency on the developer to know the right method names in advance.

What happens when the properties are not simple data types? For example, your bean might have a collection or a map as a property. In these cases, use PropertyUtils.getIndexedProperty or PropertyUtils.getMappedProperty. Indexed properties require you to pass the index of the value within the collection that you want to get or set. Mapped properties require you to pass the key of the value you want to get or set. For example:

PropertyUtils.setIndexedProperty(
    app1Bean, "listProp1[1]", "New String value 1"); 
System.err.println("App1LayerBean, listProp1[1]: " +
    PropertyUtils.getIndexedProperty(app1Bean, "listProp1[1]"));

Notice how, for indexed properties, the value of the index is passed within square brackets. The example above sets the value at index 1 of the list in the bean app1Bean to New String value 1, while the line after that retrieves the same value at index 1. An alternate way of doing the same thing is to use the methods PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value) and PropertyUtils.getIndexedProperty(Object bean, String name, int index), where the index is passed as a method parameter. Similar methods exist for mapped properties where you pass the key, not the index, to get and set mapped values.

Finally, your bean might itself have other beans as properties. What happens when you want to get or set the property of the bean that is contained as a property within your primary bean? Use the PropertyUtils.getNestedProperty(Object bean, String name) and PropertyUtils.setNestedProperty(Object bean, String name, Object value) methods, as shown below.

// accessing and setting nested properties
PropertyUtils.setNestedProperty(
    app1Bean, "subBean.stringProp",
    "Hello from SubBean, set via Nested Property Access"); 

System.err.println(
    PropertyUtils.getNestedProperty(app1Bean, "subBean.stringProp"));

As you can see, the contained bean's property is accessed via a dot nomenclature.

You can use a combination of nested, mapped, and indexed properties to any depths you like. To use a combination of these different property-access methods, use PropertyUtils.getProperty(Object bean, String name) and PropertyUtils.setProperty(Object bean, String name, Object value). For example, this would allow you to make method calls such as:

PropertyUtils.setProperty(app1Bean, "subBean.listProp[0]", 
    "Some Value");

This combines nested and indexed property access into one call.

BeanUtils is often used when dynamically accessing the request parameters for a web-based system. In fact, BeanUtils arose out of a need to transfer the request parameters dynamically into system JavaBeans in the Struts project. A user-filled form is transferred into a Map in code, where the parameter names form the keys and the parameter values are the values from by the user, and a simple BeanUtils.populate transfers these values into a system bean.

Finally, BeanUtils provides a one-step method to copy values from one bean into another:

// let's copy app1Bean to app2Bean
BeanUtils.copyProperties(app2Bean, app1Bean);

In this package, there are several other useful methods that I have not covered here. BeanUtils is one of the better-documented components. I encourage you to have a look at the Javadocs for this package for descriptions of the rest of the methods.

Pages: 1, 2, 3, 4

Next Pagearrow