RE: PropertyUtils Enhancement Source Code
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); Almost the samething i have now. I only have some more (and i don't have at this time the index because i don't believe that is nessesary, because BeanUtils / PropertyUtils are taking care of that! This is My interface that i use for quite sometime know. public interface Property { public java.util.Map getBeanProperties(); // Is needed for the new describe method in PropertyUtils!! public Object getBeanProperty(String sPropertyName); public Class[] getParameterTypes(String sName); // You should be able to get the types of the property. public void setBeanProperty(String sPropertyName, Object oPropertyValue); } 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. No! ActionServlet doesn't have to change at all!! Everychange must only be done in the PropertyUtils and BeanUtils. What does ActionServlet to do with beans? Nothing. Struts only uses the Bean And property utils for filling the beans. At this time only with reflection but i changed Bean And PropertyUtils so that it looks for the above Interface Property and then calls the get or set of that Property Interface. Here some code i changed in the PropertyUtils class: public static void setSimpleProperty(Object bean, String name, Object value) { // If it is of Property if (bean instanceof Property) { // Use that one instead of Reflection (you create youre own reflection interface) ((Property) bean).setBeanProperty(name, value); } else { // Retrieve the property setter method for the specified property PropertyDescriptor descriptor = getPropertyDescriptor(bean, name); if (descriptor == null) throw new NoSuchMethodException(Unknown property ' + name + '); Method writeMethod = getWriteMethod(descriptor); if (writeMethod == null) throw new NoSuchMethodException(Property ' + name + ' has no setter method); // Call the property setter method Object values[] = new Object[1]; values[0] = value; writeMethod.invoke(bean, values); } } 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. No tag doesn't have to be changed in my way. Because all is done throught the Property and BeanUtils classes!!! 4) Created a sub-class of ActionForm (DynamicActionForm) which implements our DynamicProperties interface. No this can be done by the programmers themself just do this: public class DynamicForm extends ActionForm implements org.apache.struts.util.Property And then they must implement the four methods. Ofcourse Struts could create a default DynamicForm that uses a Hashmap for storing its properties only the getParameterTypes would be a bit difficut then! (i will think this over) 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. If they just uses my interface then it is very easy to do this. It would be interesting to hear others opinions on how dynamic properties should be implemented. given :-) Niall Johan Compagner P.S. I am willing to give my implementation of the Property interface and the changes to BeanUtils/PropertyUtils email me if you want.
RE: PropertyUtils Enhancement Source Code
I agree with William 100%. I have to admit I was guilty of doing in my jpath code something similar to what David is doing, simply because I needed the functionality and I could not easily customize BeanUtils. Here's what I did: I introduced a DynamicPropertyHandler interface, which is like DynamicProperties interface except that it is a delegate, rather than the object itself, so it takes the target as the first argument of each call. This approach allows you to avoid allocating tons of those wrappers - you simply call the appropriate handler and pass to it the target object and the property name. In JPath I have a universal binding mechanism called JPathIntrospector, which associates an object type with the corresponding handler. So, for example, in order to work with a map, you ask the Introspector: what's the handler I should use for an object of type java.util.HashMap; it returns a MapHandler and then you pass the map and the property name to the handler to get the property value. BTW, if you want to look at the code, download www.plotnix.com/jpath/jpath.zip It is all prepared for the Jakarta repository (has been for over a month) - I am just waiting for a user id. Anyway, I only added Dynamic Property Handler to JPath because I could not add it directly to PropertyUtils. I think PropertyUtils is the only right place for it and the solution should be universal. Well, actually, the JDK is the only truly right place, but we cannot change that one, can we? - Dmitri Plotnikov [EMAIL PROTECTED] William Shulman wrote: 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
RE: PropertyUtils Enhancement Source Code
Johan I take that as definite No! with no room for negotiation - oh shit, better tell my boss I did it all wrong ;) As I said to William... The problem of implementing this using the Struts BeanUtils is that it has been deprecated because its been donated to the Jakarta Commons project - will we be able to persuade Jakarta Commons to include this when it doesn't have anything to do with JavaBeans? My interface is more minimalistic than yours because its tightly focused on all Struts needs to do i.e. get and set values. How people implement it is up to them - how properties a stored (doesn't have to be a HashMap), getting a list of properties (i.e your getBeanProperties() method) and type conversion can all be implemented in your own flavour of ActionForm (which is what we did). Thanks for your offer of code - these aspects of our system are done and working and I really want to see what Struts does because if it suits us, better to use the vanilla Struts solution. Niall -Original Message- From: Johan Compagner [mailto:[EMAIL PROTECTED]] Sent: 30 May 2001 10:07 To: [EMAIL PROTECTED] Subject: RE: PropertyUtils Enhancement Source Code 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); Almost the samething i have now. I only have some more (and i don't have at this time the index because i don't believe that is nessesary, because BeanUtils / PropertyUtils are taking care of that! This is My interface that i use for quite sometime know. public interface Property { public java.util.Map getBeanProperties(); // Is needed for the new describe method in PropertyUtils!! public Object getBeanProperty(String sPropertyName); public Class[] getParameterTypes(String sName); // You should be able to get the types of the property. public void setBeanProperty(String sPropertyName, Object oPropertyValue); } 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. No! ActionServlet doesn't have to change at all!! Everychange must only be done in the PropertyUtils and BeanUtils. What does ActionServlet to do with beans? Nothing. Struts only uses the Bean And property utils for filling the beans. At this time only with reflection but i changed Bean And PropertyUtils so that it looks for the above Interface Property and then calls the get or set of that Property Interface. Here some code i changed in the PropertyUtils class: public static void setSimpleProperty(Object bean, String name, Object value) { // If it is of Property if (bean instanceof Property) { // Use that one instead of Reflection (you create youre own reflection interface) ((Property) bean).setBeanProperty(name, value); } else { // Retrieve the property setter method for the specified property PropertyDescriptor descriptor = getPropertyDescriptor(bean, name); if (descriptor == null) throw new NoSuchMethodException(Unknown property ' + name + '); Method writeMethod = getWriteMethod(descriptor); if (writeMethod == null) throw new NoSuchMethodException(Property ' + name + ' has no setter method); // Call the property setter method Object values[] = new Object[1]; values[0] = value; writeMethod.invoke(bean, values); } } 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. No tag doesn't have to be changed in my way. Because all is done throught the Property and BeanUtils classes!!! 4) Created a sub-class of ActionForm (DynamicActionForm) which implements our DynamicProperties interface. No this can be done by the programmers themself just do this: public class DynamicForm extends ActionForm implements org.apache.struts.util.Property And then they must implement the four methods. Ofcourse Struts could create a default DynamicForm that uses a Hashmap for storing its properties only the getParameterTypes would be a bit difficut then! (i will think this over) 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. If they just uses my interface then it is very
RE: PropertyUtils Enhancement Source Code
The problem with your suggestion of implementing this using the Struts BeanUtils is that it has been deprecated because its been donated to the Jakarta Commons project. I understand Struts will be changed to use the Jakarta Commons version in 1.1. BeanUtils are utility methods for populating JavaBeans and the question is would we be able to persuade Jakarta Commons to include this when it doesn't have anything to do with JavaBeans? This should not be that big of an issue. AND, DynamicPropertyMappers (or whatever we want to call them) has everything to do with JavaBeans in my opinion. -will
RE: PropertyUtils Enhancement Source Code
The problem with your suggestion of implementing this using the Struts BeanUtils is that it has been deprecated because its been donated to the Jakarta Commons project. I understand Struts will be changed to use the Jakarta Commons version in 1.1. BeanUtils are utility methods for populating JavaBeans and the question is would we be able to persuade Jakarta Commons to include this when it doesn't have anything to do with JavaBeans? This should not be that big of an issue. AND, DynamicPropertyMappers (or whatever we want to call them) has everything to do with JavaBeans in my opinion. -will OK so get on bugzilla and submit your proposal as an enhancement to Jakarta Commons. AND, I don't see this in the JavaBeans spec (nice as it would be). http://java.sun.com/products/javabeans/docs/spec.html Niall
RE: PropertyUtils Enhancement Source Code
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
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
Re: PropertyUtils Enhancement Source Code
I hear what you are saying. You see maps as a first order concept that you would like formalized in the syntax of bean expressions. I can see that, but I still do favor staying as close to the original bean specification as we can without loosing expressiveness. Because using the '.' operator requires no syntactic changes to the expression language and can implement the same semantics as 'map{key}', I see no reason to add new base contructs to the language. -will David Winterfeldt writes: 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.