I think this *may* solve the problem at the wrong level of abstraction. The
concept of Dynamic Properties, while useful in dealing with forms, has
nothing to do with forms and ActionForms intrinsicly. Dynamic
Properties should be available as a tool for any Java programming
task. I can think of many uses that do not even involve web
applications. To couple the idea of Dynamic properties to web forms
would be a mistake.
That said, your solution below does not, per say, couple Dynamic
properties to ActionForms. It seems that you just want to use Dynamic
properties with ActionForms, which seems fine to me. Otherwise, you
suggestion is very similar to the implementation approach I outlined
below.
Without question, however, Dynamic Properties should be part of the
struts beans package. Of course I am biased ;), but I think the
implementation I outlined in my last email on the topic (below) is the
right way to do this (similar to Niall's approach). There are
differences, however, with Niall's. For one, getValue and setValue
should deal with Objects and not Strings. My solution also contains
the concept of a registry for registering dynamic PropertyMappers
and how it should be integrated with the PropertyUtils class.
-will
Niall Pemberton writes:
> I would prefer to see dynamic properties for ActionForms implemented in
> Struts - which is on the 1.1 ToDo list.
>
> We have customized Struts to do dynamic properties along the following
> lines:
>
> 1) Created a "DynamicProperties" interface which has the following methods:
>
> public String getValue(String property);
> public String getValue(int index, String property);
> public void setValue(String property, String value);
> public void setValue(int index, String property, String value);
>
> 2) Sub-classed "ActionServlet" and changed the "processPopulate" method to
> populate the ActionForm using the above setters if its an instance of
> "DynamicProperties" or using its normal reflection if not.
>
> 3) Modified Struts tags to retrieve bean values using the above getters if
> its an instance of "DynamicProperties" or using its normal reflection if
> not.
>
> 4) Created a sub-class of ActionForm (DynamicActionForm) which implements
> our "DynamicProperties" interface.
>
> Now we only have one DynamicActionForm and don't have to go round setting up
> loads of different "ActionForm" classes. The DynamicActionForm is a bit
> simplistic and wouldn't suit everyones needs, but the advantage of this is
> people could create their own concrete implementations.
>
> It would be interesting to hear others opinions on how dynamic properties
> should be implemented.
>
> Niall
>
>
> > -----Original Message-----
> > From: David Winterfeldt [mailto:[EMAIL PROTECTED]]
> > Sent: 28 May 2001 16:59
> > To: [EMAIL PROTECTED]
> > Subject: Re: PropertyUtils Enhancement Source Code
> >
> >
> > I always like doing things more generic, but in this
> > particular case I like being able to tell that a value
> > in a long nested property was a key for a
> > java.util.Map.
> >
> > "foo.someMap.firstPerson.address.zip"
> > vs.
> > "foo.someMap{firstPerson}.address.zip"
> >
> > It seems like the most common/standard things you
> > would store something in are arrays, Collection/List,
> > and a Map. I'm not sure if the indexed property can
> > handle a Collection or a Collection/List, but it could
> > easily be modified if it doesn't. The only other
> > thing left is a Map. So I don't think it is that bad
> > to have special syntax. There is improved readability
> > and it would cover the final major interface not cover
> > by nested properties from the Collections API.
> >
> > It would still be nice to have a generic way to plug
> > in something for other classes though. We'll see what
> > other people think.
> >
> > David
> >
> > --- William Shulman <[EMAIL PROTECTED]> wrote:
> > >
> > > David-
> > >
> > > I think your idea is a great one. Ideally, you would
> > > configure the
> > > BeanInfo for Map like classes with a readMethod that
> > > treats the names
> > > of Map properties as keys. That way the evalulation
> > > expression
> > > "foo.someMap.firstName" would result in 'firstName'
> > > being treated as a key
> > > to be looked up in the Map and returned. This is the
> > > way the java
> > > beans specification exposes hooks to "override" when
> > > the '.' operator
> > > does.
> > >
> > > Unfortunately, doing this in practice is quite
> > > difficult. Without going into
> > > the details, if you investigate this method in the
> > > java beans API's you will
> > > find it quite inflexible. However, the idea is
> > > right. We should be able to
> > > explicitly define how properties of a given type are
> > > accessed and mutated.
> > >
> > > I think the right way to implement this is to create
> > > an interface called
> > > PropertyMapper and support a mechanism for linking
> > > property mappers
> > > with java Classes via a PropertyMapperRegistry.
> > >
> > > public interface PropertyMapper {
> > > public Object getProperty(Object bean, String
> > > propName);
> > > public Object setProperty(Object bean, String
> > > propName, Object propValue);
> > > }
> > >
> > > public class PropertyMapperRegistry {
> > > public PropertyMapper getPropertyMapper(Class
> > > type);
> > > public void registerPropertyMapper(Class type,
> > > PropertyMapper pm);
> > > }
> > >
> > > Then, the struts PropertyUtils.getPropertyValue and
> > > setPropertyValue methods
> > > (I might have the names slightly wrong) would first
> > > look to see if a
> > > PropertyMapper is registered for a given type, and
> > > use that PropertyMapper if
> > > possible. If a PropertyMapper is not registered for
> > > a given type, then the
> > > PropertyUtils falls back to the standard readMethod
> > > and writeMethod supplied
> > > by the property's PropertyDescriptor.
> > >
> > > Here is how you would implement a PropertyMapper for
> > > HashMaps
> > >
> > > public class HashMapPropertyMapper implements
> > > PropertyMapper {
> > > public Object getProperty(Object bean, String
> > > propName) {
> > > return( ((HashMap)bean).get(propName) );
> > > }
> > >
> > > public Object setProperty(Object bean, String
> > > propName, Object propValue) {
> > > return( ((HashMap)bean).put(propName, propValue)
> > > );
> > > }
> > > }
> > >
> > > The reason I favor this approach is:
> > > (1) This method is very close the initial spirit of
> > > the Java Beans spec
> > > (2) No new syntax is introduced. We do not need { }
> > > and can utilize the
> > > existing '.' (dot) operator.
> > > (3) This solution is more general than a solution
> > > just for HashMaps.
> > > Although this is applied really well to HashMaps,
> > > With this method,
> > > we can implement PropertyMappers for any class. One
> > > example that comes to
> > > mind is this (although slightly academic):
> > >
> > > Imagine we have a FileManager class that we use to
> > > create java.io.File
> > > objects (kind of a File Factory). We might want to
> > > abstractly define that
> > > a properties of FileManagers are File objects
> > > obtained through the
> > > FileManager, such that we can write expressions like
> > > this:
> > >
> > "someObject.myFileManager./usr/local/apache/logs/error"
> > >
> > > To put it simply, we can make the '.' operator mean
> > > anything we want it to mean
> > > for a given target class. Kind of cool. This kind of
> > > thing can also be seen
> > > in the Python programming language where the
> > > developer can override the
> > > imlementation of '.' and is also similar to 'tie' in
> > > Perl .
> > >
> > > -will
> > >
> > >
> > >
> > >
> > > David Winterfeldt writes:
> > > > Here is the source. I've done some basic tests
> > > and I
> > > > think everything is working.
> > > >
> > > > David
> > > >
> > > > --- David Winterfeldt <[EMAIL PROTECTED]>
> > > wrote:
> > > > > For an array you can do this for a property
> > > > > "type[index]". I don't know if this has been
> > > > > suggested before, but what if you could also do
> > > this
> > > > > for a Hashmap. I was thinking something like
> > > > > form{name}. I'm sure there are lots of other
> > > uses,
> > > > > but it could let you make a bean/form class
> > > that
> > > > > just
> > > > > used a Hashmap for rapid prototyping. This
> > > also
> > > > > might
> > > > > be a simple/temporary solution for the beans
> > > that
> > > > > don't need setters and getters.
> > > > >
> > > > > public Hashmap getForm();
> > > > >
> > > > > <html:text property="form{firstName}" size="30"
> > > > > maxlength="30"/>
> > > > > <html:text property="form{lastName}" size="30"
> > > > > maxlength="30"/>
> > > > > <html:text property="form{address}" size="30"
> > > > > maxlength="30"/>
> > > > >
> > > > >
> > > > > David
> > > > >
> > > > >
> > > __________________________________________________
> > > > > Do You Yahoo!?
> > > > > Yahoo! Auctions - buy the things you want at
> > > great
> > > > > prices
> > > > > http://auctions.yahoo.com/
> > > >
> > > >
> > > >
> > > __________________________________________________
> > > > Do You Yahoo!?
> > > > Yahoo! Auctions - buy the things you want at
> > > great prices
> > > > http://auctions.yahoo.com/
> >
> >
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! Auctions - buy the things you want at great prices
> > http://auctions.yahoo.com/
> >
>