![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.commons.beanutils2.package-info Maven / Gradle / Ivy
Show all versions of commons-beanutils2 Show documentation
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** *
orThe Bean Introspection Utilities component of the Apache Commons * subproject offers low-level utility classes that assist in getting and setting * property values on Java classes that follow the naming design patterns outlined * in the JavaBeans Specification, as well as mechanisms for dynamically defining * and accessing bean properties.
* *Table of Contents
* **
* * *- 1. Overview *
**
*- 1.1 Background
*- 1.2 External Dependencies
*- 2. Standard JavaBeans *
**
*- 2.1 Background
*- 2.2 Basic Property Access
*- 2.3 Nested Property Access
*- 2.4 Customizing Introspection
*- 2.5 Suppressing Properties
*- 3. Dynamic Beans (DynaBeans) * *
*- 4. Data Type Conversions *
**
*- 4.1 Background
*- 4.2 BeanUtils and ConvertUtils * Conversions
*- 4.3 Defining Your Own Converters
*- 4.4 Locale Aware Conversions
*- 5. Utility Objects And Static Utility Classes
*- 6. Collections *
*- 7. Frequently Asked Questions *
*1. Overview
* * *1.1 Background
* *The JavaBeans name comes from a * Java API * for a component architecture for the Java language. Writing Java classes that * conform to the JavaBeans design patterns makes it easier for Java developers * to understand the functionality provided by your class, as well as allowing * JavaBeans-aware tools to use Java's introspection capabilities to * learn about the properties and operations provided by your class, and present * them in a visually appealing manner in development tools.
* *The JavaBeans * Specification describes the complete set of characteristics that makes * an arbitrary Java class a JavaBean or not -- and you should consider reading * this document to be an important part of developing your Java programming * skills. However, the required characteristics of JavaBeans that are * important for most development scenarios are listed here:
**
- The class must be public, and provide a * public constructor that accepts no arguments. This allows * tools and applications to dynamically create new instances of your bean, * without necessarily knowing what Java class name will be used ahead of * time, like this: *
** String className = ...; * Class beanClass = Class.forName(className); * Object beanInstance = beanClass.newInstance(); *- As a necessary consequence of having a no-arguments constructor, * configuration of your bean's behavior must be accomplished separately * from its instantiation. This is typically done by defining a set of * properties of your bean, which can be used to modify its behavior * or the data that the bean represents. The normal convention for * property names is that they start with a lower case letter, and be * comprised only of characters that are legal in a Java identifier.
*- Typically, each bean property will have a public getter and * setter method that are used to retrieve or define the property's * value, respectively. The JavaBeans Specification defines a design * pattern for these names, using {@code get
set} as the * prefix for the property name with it's first character capitalized. Thus, * you a JavaBean representing an employee might have * (among others) properties named {@code firstName}, * {@code lastName
, andhireDate}, with method signatures * like this: *
prefix instead of a* public class Employee { * public Employee(); // Zero-arguments constructor * public String getFirstName(); * public void setFirstName(String firstName); * public String getLastName(); * public void setLastName(String lastName); * public Date getHireDate(); * public void setHireDate(Date hireDate); * public boolean isManager(); * public void setManager(boolean manager); * public String getFullName(); * } **As you can see from the above example, there is a special variant allowed * for boolean properties -- you can name the getter method with a * {@code is get} prefix if that makes * for a more understandable method name. *
method inherited fromIf you have both a getter and a setter method for a * property, the data type returned by the getter must match the * data type accepted by the setter. In addition, it is contrary * to the JavaBeans specification to have more than one setter * with the same name, but different property types. *It is not required that you provide a getter and a * setter for every property. In the example above, the * {@code fullName} property is read-only, because there is no * setter method. It is also possible, but less common, to provide * write-only properties. *It is also possible to create a JavaBean where the getter and * setter methods do not match the naming pattern described above. * The standard JavaBeans support classes in the Java language, as well as * all classes in the BeanUtils package, allow you to describe the actual * property method names in a {@code BeanInfo} class associated with * your bean class. See the JavaBeans Specification for full details. *The JavaBeans Specification also describes many additional design patterns * for event listeners, wiring JavaBeans together into component hierarchies, * and other useful features that are beyond the scope of the BeanUtils * package. * * *Using standard Java coding techniques, it is very easy to deal with * JavaBeans if you know ahead of time which bean classes you will be using, and * which properties you are interested in:
** Employee employee = ...; * System.out.println("Hello " + employee.getFirstName() + "!"); ** * *1.2 External Dependencies
* *The commons-beanutils package requires that the following * additional packages be available in the application's class path at runtime: *
**
* * *- * Logging Package (Apache Commons), version 1.0 or later
*- * Collections Package (Apache Commons), version 1.0 or later
*2. Standard JavaBeans
* * *2.1 Background
* *As described above, the standard facilities of the Java programming language * make it easy and natural to access the property values of your beans using * calls to the appropriate getter methods. * But what happens in more sophisticated environments where you do not * necessarily know ahead of time which bean class you are going to be using, * or which property you want to retrieve or modify? The Java language provides * classes like {@code java.beans.Introspector}, which can examine a Java * class at runtime and identify for you the names of the property getter and * setter methods, plus the Reflection capabilities to dynamically call * such a method. However, these APIs can be difficult to use, and expose the * application developer to many unnecessary details of the underlying structure * of Java classes. The APIs in the BeanUtils package are intended to simplify * getting and setting bean properties dynamically, where the objects you are * accessing -- and the names of the properties you care about -- are determined * at runtime in your application, rather than as you are writing and compiling * your application's classes.
* *This is the set of needs that are satisfied by the static methods of the * {@link org.apache.commons.beanutils2.PropertyUtils} * class, which are described further in this section. First, however, some * further definitions will prove to be useful:
* *The general set of possible property types supported by a JavaBean can be * broken into three categories -- some of which are supported by the standard * JavaBeans specification, and some of which are uniquely supported by the * BeanUtils package:
**
* *- Simple - Simple, or scalar, properties have a single * value that may be retrieved or modified. The underlying property type * might be a Java language primitive (such as {@code int}, a simple * object (such as a {@code java.lang.String}), or a more complex * object whose class is defined either by the Java language, by the * application, or by a class library included with the application.
*- Indexed - An indexed property stores an ordered collection * of objects (all of the same type) that can be individually accessed by an * integer-valued, non-negative index (or subscript). Alternatively, the * entire set of values may be set or retrieved using an array. * As an extension to the JavaBeans specification, the * BeanUtils package considers any property whose underlying data * type is {@code java.util.List} (or an implementation of List) to be * indexed as well.
*- Mapped - As an extension to standard JavaBeans APIs, * the BeanUtils package considers any property whose underlying * value is a {@code java.util.Map} to be "mapped". You can set and * retrieve individual values via a String-valued key.
*A variety of API methods are provided in the * {@link org.apache.commons.beanutils2.PropertyUtils} class to get and set * property values of all of these types. * In the code fragments below, assume that there are two bean classes defined * with the following method signatures:
** public class Employee { * public Address getAddress(String type); * public void setAddress(String type, Address address); * public Employee getSubordinate(int index); * public void setSubordinate(int index, Employee subordinate); * public String getFirstName(); * public void setFirstName(String firstName); * public String getLastName(); * public void setLastName(String lastName); * } ** * *2.2 Basic Property Access
* *Getting and setting simple property values is, well, * simple :-). Check out the following API signatures in the Javadocs:
* **
* *- {@link org.apache.commons.beanutils2.PropertyUtils#getSimpleProperty(Object, String)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setSimpleProperty(Object, String, Object)}
*Using these methods, you might dynamically manipulate the employee's name * in an application:
** Employee employee = ...; * String firstName = (String) * PropertyUtils.getSimpleProperty(employee, "firstName"); * String lastName = (String) * PropertyUtils.getSimpleProperty(employee, "lastName"); * ... manipulate the values ... * PropertyUtils.setSimpleProperty(employee, "firstName", firstName); * PropertyUtils.setSimpleProperty(employee, "lastName", lastName); ** *For indexed properties, you have two choices - you can * either build a subscript into the "property name" string, using square * brackets, or you can specify the subscript in a separate argument to the * method call:
* **
* *- {@link org.apache.commons.beanutils2.PropertyUtils#getIndexedProperty(Object, String)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#getIndexedProperty(Object, String, int)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setIndexedProperty(Object, String, Object)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setIndexedProperty(Object, String, int, Object)}
*Only integer constants are allowed when you add a subscript to the property * name. If you need to calculate the index of the entry you wish to retrieve, * you can use String concatenation to assemble the property name expression. * For example, you might do either of the following:
** Employee employee = ...; * int index = ...; * String name = "subordinate[" + index + "]"; * Employee subordinate = (Employee) * PropertyUtils.getIndexedProperty(employee, name); * * Employee employee = ...; * int index = ...; * Employee subordinate = (Employee) * PropertyUtils.getIndexedProperty(employee, "subordinate", index); ** *In a similar manner, there are two possible method signatures for getting * and setting mapped properties. The difference is that the * extra argument is surrounded by parentheses ("(" and ")") instead of square * brackets, and it is considered to be a String-value key used to get or set * the appropriate value from an underlying map.
* **
* *- {@link org.apache.commons.beanutils2.PropertyUtils#getMappedProperty(Object, String)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#getMappedProperty(Object, String, String)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setMappedProperty(Object, String, Object)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setMappedProperty(Object, String, String, Object)}
*You can, for example, set the employee's home address in either of these * two manners:
* ** Employee employee = ...; * Address address = ...; * PropertyUtils.setMappedProperty(employee, "address(home)", address); * * Employee employee = ...; * Address address = ...; * PropertyUtils.setMappedProperty(employee, "address", "home", address); ** * *2.3 Nested Property Access
* *In all of the examples above, we have assumed that you wished to retrieve * the value of a property of the bean being passed as the first argument to a * PropertyUtils method. However, what if the property value you retrieve is * really a Java object, and you wish to retrieve a property of that * object instead?
* *For example, assume we really wanted the {@code city} property of the * employee's home address. Using standard Java programming techniques for direct * access to the bean properties, we might write:
* ** String city = employee.getAddress("home").getCity(); ** *The equivalent mechanism using the PropertyUtils class is called * nested property access. To use this approach, you concatenate * together the property names of the access path, using "." separators -- very * similar to the way you can perform nested property access in JavaScript.
* **
* *- {@link org.apache.commons.beanutils2.PropertyUtils#getNestedProperty(Object, String)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setNestedProperty(Object, String, Object)}
*The PropertyUtils equivalent to the above Java expression would be:
* ** String city = (String) * PropertyUtils.getNestedProperty(employee, "address(home).city"); ** *Finally, for convenience, PropertyUtils provides method signatures that * accept any arbitrary combination of simple, indexed, and mapped property * access, using any arbitrary level of nesting:
* **
* *- {@link org.apache.commons.beanutils2.PropertyUtils#getProperty(Object, String)}
*- {@link org.apache.commons.beanutils2.PropertyUtils#setProperty(Object, String, Object)}
*which you might use like this:
* ** Employee employee = ...; * String city = (String) PropertyUtils.getProperty(employee, * "subordinate[3].address(home).city"); ** * *2.4 Customizing Introspection
* *As was pointed out, BeanUtils relies on conventions defined by the * JavaBeans specification to determine the properties available for * a specific bean class. Thus all classes conforming to these conventions can * be used out of the box.
* *Sometimes an application has to deal with classes using different * conventions. For instance, fluent APIs allowing method chaining are not * compliant to the JavaBeans specification because here set methods * have non-void return values. From version 1.9.0 onwards, BeanUtils supports * customization of its introspection mechanism. This allows an application * to extend or modify the default discovery of bean properties.
* *The key to this extension mechanism is the {@link org.apache.commons.beanutils2.BeanIntrospector} * interface. The purpose of an object implementing this interface is to * process a specific target class and create corresponding * {@code PropertyDescriptor} objects for the properties it detects. * Per default, BeanUtils uses a {@link org.apache.commons.beanutils2.DefaultBeanIntrospector} * object which detects properties compatible with the JavaBeans * specification.
* *In order to extend the property discovery mechanism, {@code PropertyUtils} * offers the {@link org.apache.commons.beanutils2.PropertyUtils#addBeanIntrospector(BeanIntrospector)} * method. Here a custom {@code BeanIntrospector} implementation can be * passed in. During introspection of a class, this custom introspector is * then called, and it can add the properties it has detected to the total * result. As an example of such a custom {@code BeanIntrospector} * implementation, BeanUtils ships with the {@link org.apache.commons.beanutils2.FluentPropertyBeanIntrospector} * class. This implementation can detect properties whose set methods have a * non-void return type - thus enabling support for typical properties in a * fluent API.
* * *2.5 Suppressing Properties
*The mechanism of customizing bean introspection described in the previous * section can also be used to suppress specific properties. There is a * specialized {@code BeanIntrospector} implementation that does exactly * this: {@link org.apache.commons.beanutils2.SuppressPropertiesBeanIntrospector}. * When creating an instance, a collection with the names of properties that * should not be accessible on beans has to be provided. These properties will * then be removed if they have been detected by other {@code BeanIntrospector} * instances during processing of a bean class.
* *A good use case for suppressing properties is the special {@code class} * property which is per default available for all beans; it is generated from the * {@code getClass()
Object} which follows the * naming conventions for property get methods. Exposing this property in an * uncontrolled way can lead to a security vulnerability as it allows access to * the class loader. More information can be found at * * https://issues.apache.org/jira/browse/BEANUTILS-463. * *
andBecause the {@code class} property is undesired in many use cases * there is already an instance of {@code SuppressPropertiesBeanIntrospector} * which is configured to suppress this property. It can be obtained via the * {@code SUPPRESS_CLASS} constant of * {@code SuppressPropertiesBeanIntrospector}.
* * *3. Dynamic Beans (DynaBeans)
* * *3.1 Background
* *The {@link org.apache.commons.beanutils2.PropertyUtils} class described in the * preceding section is designed to provide dynamic property access on existing * JavaBean classes, without modifying them in any way. A different use case for * dynamic property access is when you wish to represent a dynamically calculated * set of property values as a JavaBean, but without having to actually * write a Java class to represent these properties. Besides the effort savings * in not having to create and maintain a separate Java class, this ability also * means you can deal with situations where the set of properties you care about * is determined dynamically (think of representing the result set of an SQL * select as a set of JavaBeans ...).
* *To support this use case, the BeanUtils package provides the * {@link org.apache.commons.beanutils2.DynaBean} interface, which must be implemented by a * bean class actually implementing the interface's methods, and the associated * {@link org.apache.commons.beanutils2.DynaClass} interface that defines the set of * properties supported by a particular group of DynaBeans, in much the same way * that {@code java.lang.Class} defines the set of properties supported by * all instances of a particular JavaBean class.
* *For example, the {@code Employee} class used in the examples above * might be implemented as a DynaBean, rather than as a standard JavaBean. You * can access its properties like this:
* ** DynaBean employee = ...; // Details depend on which * // DynaBean implementation you use * String firstName = (String) employee.get("firstName"); * Address homeAddress = (Address) employee.get("address", "home"); * Object subordinate = employee.get("subordinate", 2); ** *One very important convenience feature should be noted: the * PropertyUtils property getter and setter methods understand how to access * properties in DynaBeans. Therefore, if the bean you pass as the first * argument to, say, {@code PropertyUtils.getSimpleProperty()} is really a * DynaBean implementation, the call will get converted to the appropriate * DynaBean getter method transparently. Thus, you can base your application's * dynamic property access totally on the PropertyUtils APIs, if you wish, and * use them to access either standard JavaBeans or DynaBeans without having to * care ahead of time how a particular bean is implemented.
* *Because DynaBean and DynaClass are interfaces, they may be implemented * multiple times, in different ways, to address different usage scenarios. The * following subsections describe the implementations that are provided as a part * of the standard BeanUtils package, although you are encouraged to * provide your own custom implementations for cases where the standard * implementations are not sufficient.
* * *3.2 {@code BasicDynaBean
BasicDynaClass} * *
) can have the value ofThe {@link org.apache.commons.beanutils2.BasicDynaBean} and * {@link org.apache.commons.beanutils2.BasicDynaClass} implementation provides a * basic set of * dynamic property capabilities where you want to dynamically define the * set of properties (described by instances of {@link org.apache.commons.beanutils2.DynaProperty}). * You start by defining the DynaClass that establishes * the set of properties you care about:
* ** DynaProperty[] props = new DynaProperty[]{ * new DynaProperty("address", java.util.Map.class), * new DynaProperty("subordinate", mypackage.Employee[].class), * new DynaProperty("firstName", String.class), * new DynaProperty("lastName", String.class) * }; * BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props); ** *Note that the 'dynaBeanClass' argument (in the constructor of * {@code BasicDynaClass
null}. In this * case, the value of {@code dynaClass.getDynaBeanClass} will just be the * {@code Class} for BasicDynaBean. * *
instead ofNext, you use the {@code newInstance()} method of this DynaClass to * create new DynaBean instances that conform to this DynaClass, and populate * its initial property values (much as you would instantiate a new standard * JavaBean and then call its property setters):
* ** DynaBean employee = dynaClass.newInstance(); * employee.set("address", new HashMap()); * employee.set("subordinate", new mypackage.Employee[0]); * employee.set("firstName", "Fred"); * employee.set("lastName", "Flintstone"); ** *Note that the DynaBean class was declared to be * {@code DynaBean
BasicDynaBean}. In * general, if you are using DynaBeans, you will not want to care about the * actual implementation class that is being used -- you only care about * declaring that it is a {@code DynaBean} so that you can use the * DynaBean APIs. * *
andAs stated above, you can pass a DynaBean instance as the first argument * to a {@code PropertyUtils} method that gets and sets properties, and it * will be interpreted as you expect -- the dynamic properties of the DynaBean * will be retrieved or modified, instead of underlying properties on the * actual BasicDynaBean implementation class.
* * *3.3 {@code ResultSetDynaClass} (Wraps ResultSet in DynaBeans)
* *A very common use case for DynaBean APIs is to wrap other collections of * "stuff" that do not normally present themselves as JavaBeans. One of the most * common collections that would be nice to wrap is the * {@code java.sql.ResultSet} that is returned when you ask a JDBC driver * to perform a SQL SELECT statement. Commons BeanUtils offers a standard * mechanism for making each row of the result set visible as a DynaBean, * which you can utilize as shown in this example:
** Connection conn = ...; * Statement stmt = conn.createStatement(); * ResultSet rs = stmt.executeQuery * ("select account_id, name from customers"); * Iterator rows = (new ResultSetDynaClass(rs)).iterator(); * while (rows.hasNext()) { * DynaBean row = (DynaBean) rows.next(); * System.out.println("Account number is " + * row.get("account_id") + * " and name is " + row.get("name")); * } * rs.close(); * stmt.close(); ** * * *3.4 {@code RowSetDynaClass} (Disconnected ResultSet as DynaBeans)
*Although {@code ResultSetDynaClass} is * a very useful technique for representing the results of an SQL query as a * series of DynaBeans, an important problem is that the underlying * {@code ResultSet} must remain open throughout the period of time that the * rows are being processed by your application. This hinders the ability to use * {@code ResultSetDynaClass} as a means of communicating information from * the model layer to the view layer in a model-view-controller architecture * such as that provided by the Struts * Framework, because there is no easy mechanism to assure that the result set * is finally closed (and the underlying {@code Connection} returned to its * connection pool, if you are using one).
* *The {@code RowSetDynaClass} class represents a different approach to * this problem. When you construct such an instance, the underlying data is * copied into a set of in-memory DynaBeans that represent the result. * The advantage of this technique, of course, is that you can immediately close * the ResultSet (and the corresponding Statement), normally before you even * process the actual data that was returned. The disadvantage, of course, is * that you must pay the performance and memory costs of copying the result data, * and the result data must fit entirely into available heap memory. For many * environments (particularly in web applications), this tradeoff is usually * quite beneficial.
* *As an additional benefit, the {@code RowSetDynaClass} class is defined * to implement {@code java.io.Serializable}, so that it (and the * DynaBeans that correspond to each row of the result) can be conveniently * serialized and deserialized (as long as the underlying column values are * also Serializable). Thus, {@code RowSetDynaClass} represents a very * convenient way to transmit the results of an SQL query to a remote Java-based * client application (such as an applet).
* *The normal usage pattern for a {@code RowSetDynaClass} will look * something like this:
** Connection conn = ...; // Acquire connection from pool * Statement stmt = conn.createStatement(); * ResultSet rs = stmt.executeQuery("SELECT ..."); * RowSetDynaClass rsdc = new RowSetDynaClass(rs); * rs.close(); * stmt.close(); * ...; // Return connection to pool * List rows = rsdc.getRows(); * ...; // Process the rows as desired ** * * *3.5 {@code WrapDynaBean
WrapDynaClass} * *
andOK, you've tried the DynaBeans APIs and they are cool -- very simple * {@code get()
set()} methods provide easy access to all * of the dynamically defined simple, indexed, and mapped properties of your * DynaBeans. You'd like to use the DynaBean APIs to access all * of your beans, but you've got a bunch of existing standard JavaBeans classes * to deal with as well. This is where the * {@link org.apache.commons.beanutils2.WrapDynaBean} (and its associated * {@link org.apache.commons.beanutils2.WrapDynaClass}) come into play. As the name * implies, a WrapDynaBean is used to "wrap" the DynaBean APIs around an * existing standard JavaBean class. To use it, simply create the wrapper * like this: * *
being set then the* MyBean bean = ...; * DynaBean wrapper = new WrapDynaBean(bean); * String firstName = wrapper.get("firstName"); ** *Note that, although appropriate {@code WrapDynaClass} instances are * created internally, you never need to deal with them.
* * *3.6 Lazy DynaBeans
* **
* *- 1. LazyDynaBean - A Lazy * {@link org.apache.commons.beanutils2.DynaBean}
*- 2. LazyDynaMap - A light weight * {@link org.apache.commons.beanutils2.DynaBean} facade to a Map * with lazy map/list processing
*- 3. LazyDynaList - A lazy list * for {@link org.apache.commons.beanutils2.DynaBean DynaBean's}, * {@code java.util.Map}'s or POJO beans.
*- 4. LazyDynaClass - A * {@link org.apache.commons.beanutils2.MutableDynaClass} implementation.
*You bought into the DynaBeans because it saves coding all those POJO JavaBeans but * you're here because lazy caught your eye and wondered whats that about? * What makes these flavors of DynaBean lazy are the following features:
**
- Lazy property addition - lazy beans use a * {@link org.apache.commons.beanutils2.DynaClass} which implements * the {@link org.apache.commons.beanutils2.MutableDynaClass} * interface. This provides the ability to add and remove a DynaClass's * properties. Lazy beans use this feature to automatically add * a property which doesn't exist to the DynaClass when * the {@code set(name, value)} method is called.
*- Lazy List/Array growth - If an indexed property is not large * enough to accomodate the {@code index
List} or * {@code Array} is automatically grown so that it is. *
) results in either a newLazy List/Array instantiation - if an indexed * property doesn't exist then calling the {@link org.apache.commons.beanutils2.DynaBean DynaBean's} * indexed property getter/setter methods (i.e. {@code get(name, index)} or * {@code set(name, index, value) List} * or {@code Array} being instantiated. If the indexed property has not been * defined in the DynaClass then it is automatically added and a default {@code List} * implementation instantiated. *
) results in a newLazy Map instantiation - if a mapped * property doesn't exist then calling the {@link org.apache.commons.beanutils2.DynaBean DynaBean's} * mapped property getter/setter methods (i.e. {@code get(name, key)} or * {@code set(name, key, value) Map} * being instantiated. If the mapped property has not been defined in the DynaClass * then it is automatically added and a default {@code Map} implementation * instantiated. *
as aLazy Bean instantiation - if a property is defined in * the {@code DynaClass DynaBean} or regular bean and * doesn't exist in the {@code DynaBean
thenLazyDynaBean} wiill * try to instantiate the bean using a default empty constructor. * * *
facade to a1. {@link org.apache.commons.beanutils2.LazyDynaBean} is the standard lazy bean * implementation. By default it is associated with a {@link org.apache.commons.beanutils2.LazyDynaClass} * which implements the {@link org.apache.commons.beanutils2.MutableDynaClass} interface - however * it can be used with any {@code MutableDynaClass} implementation. The question is how do * I use it? - well it can be as simple as creating a new bean and then calling the getters/setters...
* ** DynaBean dynaBean = new LazyDynaBean(); * * dynaBean.set("foo", "bar"); // simple * * dynaBean.set("customer", "title", "Mr"); // mapped * dynaBean.set("customer", "surname", "Smith"); // mapped * * dynaBean.set("address", 0, addressLine1); // indexed * dynaBean.set("address", 1, addressLine2); // indexed * dynaBean.set("address", 2, addressLine3); // indexed ** *2. {@link org.apache.commons.beanutils2.LazyDynaMap} is a light weight * {@code DynaBean
Map} with all the usual lazy features. Its * light weight because it doesn't have an associated {@code DynaClass} containing all the properties. * In fact it actually implements the {@code DynaClass
interface itself (andMutableDynaClass}) * and derives all the DynaClass information from the actual contents of the {@code Map}. A * {@code LazyDynaMap
can be created around an existingMap} or can instantiate its own * {@code Map
. After anyDynaBean
processing has finished theMap} can be retrieved * and the DynaBean facade discarded. * *
used byIf you need a new {@code Map} then to use....
* ** DynaBean dynaBean = new LazyDynaMap(); // create DynaBean * * dynaBean.set("foo", "bar"); // simple * dynaBean.set("customer", "title", "Mr"); // mapped * dynaBean.set("address", 0, addressLine1); // indexed * * Map myMap = dynaBean.getMap() // retrieve the Map **or to use with an existing {@code Map} ....
* ** Map myMap = .... // exisitng Map * DynaBean dynaBean = new LazyDynaMap(myMap); // wrap Map in DynaBean * dynaBean.set("foo", "bar"); // set properties ** *3. {@link org.apache.commons.beanutils2.LazyDynaList} * is lazy list for {@link org.apache.commons.beanutils2.DynaBean DynaBeans} * {@code java.util.Map}'s or POJO beans. See the Javadoc * for more details and example usage.
* *4. {@link org.apache.commons.beanutils2.LazyDynaClass} * extends {@link org.apache.commons.beanutils2.BasicDynaClass} and implements * the MutableDynaClass interface. * It can be used with other {@code DynaBean} implementations, but it * is the default {@code DynaClass
LazyDynaBean}. * When using the {@code LazyDynaBean} there may be no need to have * anything to do with the {@code DynaClass}. However sometimes there * is a requirement to set up the {@code DynaClass} first - perhaps to * define the type of array for an indexed property, or if using the DynaBean * in restricted mode (see note below) is required. Doing so is * straight forward... * *
and get theEither create a {@code LazyDynaClass} first... * *
* MutableDynaClass dynaClass = new LazyDynaClass(); // create DynaClass * * dynaClass.add("amount", java.lang.Integer.class); // add property * dynaClass.add("orders", OrderBean[].class); // add indexed property * dynaClass.add("orders", java.util.TreeMap.class); // add mapped property * * DynaBean dynaBean = new LazyDynaBean(dynaClass); // Create DynaBean with associated DynaClass ** *or create a {@code LazyDynaBean
DynaClass}... * *
. Neither the* DynaBean dynaBean = new LazyDynaBean(); // Create LazyDynaBean * MutableDynaClass dynaClass = * (MutableDynaClass)dynaBean.getDynaClass(); // get DynaClass * * dynaClass.add("amount", java.lang.Integer.class); // add property * dynaClass.add("myBeans", myPackage.MyBean[].class); // add 'array' indexed property * dynaClass.add("myMap", java.util.TreeMap.class); // add mapped property ** *NOTE: One feature of {@link org.apache.commons.beanutils2.MutableDynaClass} is that it * has a Restricted property. When the DynaClass is restricted no properties can be added * or removed from the {@code DynaClass
LazyDynaBean
orLazyDynaMap} * will add properties automatically if the {@code DynaClass} is restricted. * * * *
and4. Data Type Conversions
* * *4.1 Background
* *So far, we've only considered the cases where the data types of the * dynamically accessed properties are known, and where we can use Java casts * to perform type conversions. What happens if you want to automatically * perform type conversions when casting is not possible? The * BeanUtils package provides a variety of APIs and design patterns * for performing this task as well.
* * *4.2 {@code BeanUtils
ConvertUtils} Conversions * *
orA very common use case (and the situation that caused the initial creation * of the BeanUtils package) was the desire to convert the set of request * parameters that were included in a * {@code javax.servlet.HttpServletRequest} received by a web application * into a set of corresponding property setter calls on an arbitrary JavaBean. * (This is one of the fundamental services provided by the * Struts Framework, which uses * BeanUtils internally to implement this functionality.)
* *In an HTTP request, the set of included parameters is made available as a * series of String (or String array, if there is more than one value for the * same parameter name) instances, which need to be converted to the underlying * data type. The {@link org.apache.commons.beanutils2.BeanUtils} class provides * property setter methods that accept String values, and automatically convert * them to appropriate property types for Java primitives (such as * {@code int
boolean}), and property getter methods that * perform the reverse conversion. Finally, a {@code populate()} method * is provided that accepts a {@code java.util.Map} containing a set of * property values (keyed by property name), and calls all of the appropriate * setters whenever the underlying bean has a property with the same name as * one of the request parameters. So, you can perform the all-in-one property * setting operation like this: * *
methods (including* HttpServletRequest request = ...; * MyBean bean = ...; * HashMap map = new HashMap(); * Enumeration names = request.getParameterNames(); * while (names.hasMoreElements()) { * String name = (String) names.nextElement(); * map.put(name, request.getParameterValues(name)); * } * BeanUtils.populate(bean, map); ** *The {@code BeanUtils} class relies on conversion methods defined in * the {@link org.apache.commons.beanutils2.ConvertUtils} class to perform the actual * conversions, and these methods are availablve for direct use as well. * WARNING - It is likely that the hard coded use of * {@code ConvertUtils} methods will be deprecated in the future, and * replaced with a mechanism that allows you to plug in your own implementations * of the {@link org.apache.commons.beanutils2.Converter} interface instead. Therefore, * new code should not be written with reliance on ConvertUtils.
* * *4.3 Defining Your Own Converters
* *The {@code ConvertUtils} class supports the ability to define and * register your own String --> Object conversions for any given Java class. * Once registered, such converters will be used transparently by all of the * {@code BeanUtils
populate()}). To * create and register your own converter, follow these steps: *
and*
* * *- Write a class that implements the {@link org.apache.commons.beanutils2.Converter} * interface. The {@code convert()} method should accept the * {@code java.lang.Class} object of your application class (i.e. * the class that you want to convert to, and a String representing the * incoming value to be converted.
*- At application startup time, register an instance of your converter class * by calling the {@code ConvertUtils.register()} method.
*4.4 Locale Aware Conversions
*The standard classes in {@code org.apache.commons.beanutils2} are not * locale aware. This gives them a cleaner interface and makes then easier to use * in situations where the locale is not important.
*Extended, locale-aware analogues can be found in *
* * * *org.apache.commons.beanutils2.locale *
. These are built along the same * lines as the basic classes but support localization.5. Utility Objects And Static Utility Classes
* *Background
** So far, the examples have covered the static utility classes ({@code BeanUtils}, * {@code ConvertUtils
PropertyUtils}). These are easy to use but are * somewhat inflexible. These all share the same registered converters and the same caches. * *
is a* This functionality can also be accessed through utility objects (in fact, the static utility * class use worker instances of these classes). For each static utility class, there is a corresponding * class with the same functionality that can be instantiated: *
* **
* *Utility Objects And Static Utility Classes ** Static Utility Class Utility Object * BeanUtils BeanUtilsBean * ConvertUtils ConvertUtilsBean * PropertyUtils PropertyUtilsBean * Creating an instances allow gives guarenteed control of the caching and registration * to the code that creates it. *
* * *6. Collections
* *6.1 Comparing Beans
** {@code org.apache.commons.beanutils2.BeanComparator
Comparator} implementation * that compares beans based on a shared property value. * * *
interface in6.2 Operating On Collections Of Beans
** The {@code Closure
commons-collections} encapsulates a block of code that * executes on an arbitrary input Object. {@code Commons-collections} contains code that allows * {@code Closures} to be applied to the contents of a Collection. For more details, see the * commons-collections * documentation. * *
is a* {@code BeanPropertyValueChangeClosure
Closure} that sets a specified property * to a particular value. A typical usage is to combine this with {@code commons-collections} * so that all the beans in a collection can have a particular property set to a particular value. * *
interface inFor example, set the activeEmployee property to TRUE for an entire collection:
** * ** // create the closure * BeanPropertyValueChangeClosure closure = * new BeanPropertyValueChangeClosure( "activeEmployee", Boolean.TRUE ); * * // update the Collection * CollectionUtils.forAllDo( peopleCollection, closure ); *
6.3 Querying Or Filtering Collections Of Beans
** The {@code Predicate
commons-collections} encapsulates an evaluation * of an input Object that returns either true or false. {@code Commons-collections} contains code * that allows * {@code Predicates} to be applied to be used to filter collections. For more details, see the * commons-collections * documentation. * *
is a* {@code BeanPropertyValueEqualsPredicate
Predicate} that evaluates a * set property value against a given value. A typical usage is * (in combination with {@code commons-collections}) * to filter collections on the basis of a property value. * *
interface inFor example, to filter a collection to find all beans where active employee is false use:
** * ** BeanPropertyValueEqualsPredicate predicate = * new BeanPropertyValueEqualsPredicate( "activeEmployee", Boolean.FALSE ); * * // filter the Collection * CollectionUtils.filter( peopleCollection, predicate ); *
6.4 Transforming Collections Of Beans
** The {@code Transformer
commons-collections} encapsulates the transformation * of an input Object into an output object. {@code Commons-collections} contains code * that allows * {@code Transformers} to be applied produce a collection of outputs from a collection of inputs. * For more details, see the * commons-collections * documentation. * *
is a* {@code BeanToPropertyTransformer
Transformer} implementation * that transforms a bean into it's property value. * *
* For example, to find all cities that are contained in the address of each person property of each bean in * a collection: *
** * ** // create the transformer * BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer( "person.address.city" ); * * // transform the Collection * Collection peoplesCities = CollectionUtils.collect( peopleCollection, transformer ); *
7. Frequently Asked Questions
* * *Why Can't BeanUtils Find My Method?
*The BeanUtils package relies on introspection rather than * reflection. This means that it will find only * JavaBean * compliant properties.
*There are some subtleties of this specification that can catch out the unwary:
**
* * *- A property can have only one set and one get method. Overloading is not allowed.
*- The {@code java.beans.Introspector} searches widely for a custom BeanInfo * class. If your class has the same name as another with a custom BeanInfo * (typically a java API class) then the {@code Introspector} may use that instead of * creating via reflection based on your class. If this happens, the only solution is to * create your own BeanInfo.
*How Do I Set The BeanComparator Order To Be Ascending/Descending?
** BeanComparator relies on an internal Comparator to perform the actual * comparisions. By default, a natural ordering comparator * is used which imposes a natural order. If you want to change the order, * then a custom Comparator should be created and passed into the * appropriate constructor. *
** For example: *
**/ package org.apache.commons.beanutils2;* import org.apache.commons.collections4.comparators.ComparableComparator; * import org.apache.commons.collections4.comparators.ReverseComparator; * import org.apache.commons.beanutils2.BeanComparator; * ... * BeanComparator reversedNaturalOrderBeanComparator * = new BeanComparator("propertyName", new ReverseComparator(new ComparableComparator())); * Collections.sort(myList, reversedNaturalOrderBeanComparator); * ... *