You can treat any object as a dynamic bean if a DynamicPropertyMapper is registered for its class or for one of its superclasses or interfaces. A DynamicPropertyMapper looks like this:

public interface DynamicPropertyMapper {
  public Object getPropertyValue(Object pBean, String pName)
    throws PropertyNotFoundException;

  public void setPropertyValue(Object pBean, String pName, Object pValue)
    throws PropertyNotFoundException;

  public DynamicBeanInfo getBeanInfo(Object pBean)
    throws IntrospectionException;
}

You can register a DynamicPropertyMapper by calling DynamicBeans.registerPropertyMapper(). The registration needs to occur in a static initializer of some class that is guaranteed to load before the first use of the kind of dynamic bean being registered. For example, the ProfileForm class (which you can find at <ATG10dir>/DPS/src/Java/atg/userprofiling/ProfileForm.java) registers a DynamicPropertyMapper for the ProfileFormHashtable class like this:

static {
    DynamicBeans.registerPropertyMapper(ProfileFormHashtable.class,
                                new ProfileFormHashtablePropertyMapper());
  }
Example: DynamicPropertyMapper for Maps

For example, the Oracle ATG Web Commerce platform includes a DynamicPropertyMapper for java.util.Map objects, which is implemented like this:

package atg.beans;

import java.beans.*;
import java.util.*;

/**
 * <P>Implementation of DynamicPropertyMapper that can work with any
 * subclass of java.util.Map.
**/

public class MapPropertyMapper
implements DynamicPropertyMapper
{
  //-------------------------------------
  // CONSTRUCTORS
  //-------------------------------------

  public MapPropertyMapper() {
  }

  //-------------------------------------
  // METHODS
  //-------------------------------------

  /**
   * Gets the value of the dynamic property from the specified object.
   */
  public Object getPropertyValue(Object pBean, String pPropertyName)
       throws PropertyNotFoundException
  {
    Object value  = ((Map)pBean).get(pPropertyName);
    /*
     * There happens to be one property defined on the "map bean"
     * which we take advantage of in a few places due to the isEmpty
     * method. We treat this as a special case.
     */
    if (value == null && pPropertyName.equals("empty"))
      return ((Map) pBean).isEmpty() ? Boolean.TRUE : Boolean.FALSE;
    return value;
  }

  /**
   * Sets the value of the dynamic property from the specified object.
   */
  public void setPropertyValue(Object pBean, String pPropertyName, Object pValue)
  {
    ((Map)pBean).put(pPropertyName, pValue);
  }

  public DynamicBeanInfo getBeanInfo(Object pBean)
       throws IntrospectionException
}

The existence of such a DynamicPropertyMapper lets you insert values into Hashtables using a tag like this in a JSP:

<dsp:setvalue bean="MyComponent.hashtableProp.foo" value="23"/>

This tag looks up the MyComponent bean, calls the getHashtableProp(), method, and calls the dynamic bean method setPropertyValue(hashtableProp, "foo", "23").

Multiple Property Mappers

What happens if an object has more than one superclass or interface with a registered DynamicPropertyMapper? If the definitions are at different levels of the inheritance hierarchy, the DynamicPropertyMapper of the most specific definition is used—that is, the one closest to the actual concrete class of the DynamicBean. If the object implements multiple interfaces that have DynamicPropertyMappers, the one that was declared first in the object class’s implements clause wins. For example, an atg.userprofiling.Profile object has a DynamicPropertyMapper registered for itself, and for its atg.repository.RepositoryItem interface. The Profile DynamicPropertyMapper is used for it, rather than the RepositoryItem one.


Copyright © 1997, 2012 Oracle and/or its affiliates. All rights reserved. Legal Notices