Contents
This document
What is JBeans?
Why use JBeans?
What does JBeans replace?
Making life easier
Installation
Building
Case studies/scenarios
First steps/definitions
Using BeanProperty
Using IndexedBeanProperty
Using NestedBeanProperty
Using DynamicNestedBeanProperty
Using JavaBean
Events and conversion
Using NestedBeanProperty

Although the NestedBeanProperty differs greatly in the goals it accomplishs, it behaves identical to the BeanProperty and IndexedBeanProperty classes in that it provides access to Java bean properties. This class even uses the same methods to change and retrieve the property's value (ie getPropertyValue and setPropertyValue). The difference between the last two classes and this one is that the NestedBeanProperty is designed to provide access to nested properties. Of course, it can also provide access to local properties, but it handles indexed properties quite differently.

First we will start off with examples of nested properties and how to change and retrieve them using the NestedBeanProperty class. When the class is constructed, you must provide it ALL the information that it needs to change and retrieve the property values. Since a nested property can be composed of both normal and indexed properties, this means that when constructed, all indexes for indexed properties in the nesting must be provided. Confused? Well, here's an example of using the constuctor:

    NestedBeanProperty property = new NestedBeanProperty("foo[1].bar.value", Foo.class);
    

Although this example does nothing useful, it shows that in constructing the NestedBeanProperty, you must provide all the indexes required to change and retrieve the property. This is invalid:

    NestedBeanProperty property = new NestedBeanProperty("foo.bar.value", Foo.class);
    

The reason is that foo is an indexed property and the NestedBeanProperty class will assume that since no index was specified that it is a normal property. It will be unable to find the normal property named foo and an exception will be thrown.

Here are the constructor signatures for the NestedBeanProperty. They are identical to the BeanProperty and IndexedBeanProperty with respect to the list of parameters but as shown above, the propertyName parameter behaves quite differently.

    public NestedBeanProperty(String propertyName, Class beanClass) 
    throws BeanException;
    
    public NestedBeanProperty(String propertyName, Class beanClass, boolean strict) 
    throws BeanException;
    

The second constructor is a bit different. It provides a third parameter named strict. This parameter sets the strictness of the NestedBeanProperty class. The strictness determines how the class behaves when null values are encountered. If you recall from our definitions, auto-generation, you can probably deduce that the strictness parameter controls whether or not auto-generation takes place when changing nested properties. But, in addition to this, the strictness controls something else. It also controls how the NestedBeanProperty class behaves when non-leaf properties in the nesting return null and the property's value is being retrieved. In this case, auto-generation doesn't make sense because it is overhead that will just slow things down. Instead, the strictness determines whether or not an exception is thrown or whether null is returned. If the strictness is set to false (off), then null is returned. If the strictness is set to true (on), then an exception is thrown.

 
Changing and retrieving

Now let's do some examples of how to use the NestedBeanProperty to change and retrieve nested properties. First, remember that the signatures for the getPropertyValue and setPropertyValue for the NestedBeanProperty are identical to those for the BeanProperty.

    /* Here are the Java bean classes we will use in our examples */
    public class User {
        private String name;
        private Address address;
        
        public String getName() { return name; }
        public void setName(String value) { name = value; }
        
        public Address getAddress() { return address; }
        public void setAddress(Address value) { address = value; }
    }

    public class Address {
        private String city;
        private Type type;
        
        public String getCity() { return city; }
        public void setCity(String value) { city = value; }
        
        public Type getType() { return type; }
        public void setType(Type value) { type = value; }
    }
    
    public class Type {
        private int typeCode;
        
        public int getTypeCode() { return typeCode; }
        public void setTypeCode(int value) { typeCode = value; }
    }
    
    // Retrieving the typeCode property using NestedBeanProperty
    User userInstance = new User();
    Address addressInstance = new Address();
    Type typeInstance = new Type();
    
    typeInstance.setTypeCode(42);
    addressInstance.setType(typeInstance);
    userInstance.setAddress(addressInstance);
    
    try {
        NestedBeanProperty property = new NestedBeanProperty("address.type.typeCode", User.class);
        
        // Get the typeCode property
        Integer typeCode = (Integer) property.getPropertyValue(userInstance);
        System.out.println("The type code is: " + typeCode);
    } catch (BeanException be) {
        be.printStackTrace();
    }
    
    /*
    Output:
    The type code is: 42
    */
    

As you can see, the nested property is retrieved using one simple statement. This makes developing with nested properties extremely simple. Setting the properties are the same, but in the next example we're going to throw in some indexed properties as well.

    /* Here's the new User Java bean, everything else stays the same */
    public class User {
        private String name;
        private Address [] address = new Address[2];
        
        public String getName() { return name; }
        public void setName(String value) { name = value; }
        
        public Address getAddress(int index) { return address[index]; }
        public void setAddress(int index, Address value) { address[index] = value; }
    }
    
    // Setting the typeCode property using NestedBeanProperty
    User userInstance = new User();
    Address addressInstance = new Address();
    Type typeInstance = new Type();
    
    addressInstance.setType(typeInstance);
    userInstance.setAddress(0, addressInstance);
    
    try {
        NestedBeanProperty property = new NestedBeanProperty("address[0].type.typeCode", User.class);
        property.setPropertyValue(userInstance, new Integer(42));
        System.out.println("The type code is: " + user.getAddress(0).getType().getTypeCode());
    } catch (BeanException be) {
        be.printStackTrace();
    }
    
    /*
    Output:
    The type code is: 42
    */
    

As you can see, changing the property is also very simple. Notice that the index of the address in the User Java bean was determined when the NestedBeanProperty was constructed. This is important because currently there is no way to change the index dynamically (although this is being added to the next release).

 
Strictness

Before we move on, it is important to show some examples of using the strictness of the NestedBeanProperty class. The strictness of the class can be changed after construction using these methods:

    public boolean isStrict();
    
    public void setStrict(boolean strictness);
    

All the examples above show cases where auto-generation is never needed and there are no null non-leaf nested properties (when retrieving property values). The next few examples show either auto-generation or how retrieval returns null for null non-leaf properties. These can be tricky to read and you should read through until you understand them. We'll use the Java beans from above, including the User with the indexed address property.

    // Retrieving the typeCode without creating the required objects
    User userInstance = new User();
    
    try {
        NestedBeanProperty property = new NestedBeanProperty("address[0].type.typeCode", User.class);
        property.setStrict(false);
        Integer typeCode = (Integer) property.getPropertyValue(userInstance);
        System.out.println("The type code is: " + typeCode);
    } catch (BeanException be) {
        be.printStackTrace();
    }
    
    /*
    Output:
    The type code is: null
    */
    
    // This would cause NullPointerExceptions because getAddress(0) returns null
    /*
    System.out.println("The type code is: " + userInstance.getAddress(0).getType().getTypeCode());
    */
    
    // Setting the typeCode without creating the required objects
    User userInstance = new User();
    
    try {
        NestedBeanProperty property = new NestedBeanProperty("address[0].type.typeCode", User.class);
        property.setStrict(false);
        property.setPropertyValue(userInstance, new Integer(42));
        System.out.println("The type code is: " + userInstance.getAddress(0).getType().getTypeCode());
    } catch (BeanException be) {
        be.printStackTrace();
    }
    
    /*
    Output:
    The type code is: 42
    */
    
    // This does not cause NullPointerExceptions because auto-generation created and set the 
    // address[0] property and the type property
    System.out.println("The type code is: " + userInstance.getAddress(0).getType().getTypeCode());
    
    /*
    Output:
    The type code is: 42
    */
    

As you can see, when retrieving properties that contain null values for a non-leaf property, null is returned. Notice also that we explictly set the strictness to false. This is also the default strictness for the NestedBeanProperty class, so we could remove those lines and the code would function the same. The next examples however cause exceptions because we set the strictness to true.

    // Retrieving the typeCode without creating the required objects
    User userInstance = new User();
    
    try {
        NestedBeanProperty property = new NestedBeanProperty("address[0].type.typeCode", User.class);
        property.setStrict(true);
        Integer typeCode = (Integer) property.getPropertyValue(userInstance);
        System.out.println("The type code is: " + typeCode);
    } catch (BeanException be) {
        System.out.println("The strictness threw an exception");
    }
    
    /*
    Output:
    The strictness threw an exception
    */
    
    // Setting the typeCode without creating the required objects
    User userInstance = new User();
    
    try {
        NestedBeanProperty property = new NestedBeanProperty("address[0].type.typeCode", User.class);
        property.setStrict(true);
        property.setPropertyValue(userInstance, new Integer(42));
        System.out.println("The type code is: " + userInstance.getAddress(0).getType().getTypeCode());
    } catch (BeanException be) {
        System.out.println("The strictness threw an exception");
    }
    
    /*
    Output:
    The strictness threw an exception
    */
    

As you can see, when ever a null value is encountered within the nesting and the strictness for the NestedBeanProperty class is set to true, an exception is thrown. This is the case for both updating and retrieval. From all of these examples, you can see how the strictness of the class controls its behavior for the two different types of access when null values are encountered.