On 06/27/2010 06:27 PM, Nikolaos Giannopoulos wrote: > Thomas Menke wrote: >> For the record I answer my own question: >> >> Thomas Menke wrote: >> >>> Problem is: I need to instantiate customer based on the information in >>> customerType. But before I can read customerType I can't instantiate the >>> correct class because I don't know which type. And after the >>> customerType has been set by stripes it is already too late because >>> stripes already tried and failed to set the customer.name property. >>> > First of all - Thank You for sharing your solution!!! :-)
You are welcome :-). > > That's an interesting problem. So you would like your customerType > setter method - as a side effect (if I can call it that) - to create the > appropriate customer subclass and you want to have a pre-specified > ordering on the execution of the setter methods of the action bean for > everything to work. Interesting... . > > I commented on this primarily because I have a similar need and had to > think about how I would go about solving it. Nice to know that I am not the only one... > >>> What would be the "best" way to deal with this? >>> > Not sure if this is a written best practice no-no or not but relying on > a setter to produce the appropriate class before other setter methods > get called is not the "best" way to deal with this class of problem in > my personal opinion... . An alternative idea is presented later (below). > >> Stripes populates the values in order of the length of the name of the >> property. Thus I just need to make sure that this: >> public Customer.Type customerType; >> is shorter than that: >> public Customer customer; >> > Wow. Okay. So that sounds like your design is relying on a "very" > specific coding / implementation in the Stripes framework. > > Question: Does this specific Stripes "implementation" equally apply to > Stripes 1.6? > Question: Can this specific Stripes "implementation" be guaranteed to > ALWAYS work this way and never be refactored in the future? These were pretty much the questions that I asked as well. And I am still not 100% comfortable with the answers but it is reasonable to expect that this behavior remains, because stripes HAS to make sure that an object is set before it's nested properties are set. The clue is that the request parameters are ordered by length. Thus parameters like this: myitem.nested myitem.otherNested myItem myItem.foo are reordered to the following list: myItem myItem.foo myitem.nested myitem.otherNested Since the property's name of objects that contain nested values are prepended it is guaranteed that any property's name is shorter than the names of the nested properties of the property. Of course it is possible that in future versions that stripes introduces a different way of ensuring that properties are assigned before their nested properties are exchanged. But since the current version has a purpose this will not be changed from one minor version to the next (I hope). Though yes, I would be more comfortable if this would be a documented feature. If we can extend this discussion to a reasonable length, than it might become just that ;-). > Question: Can you always guarantee a newer variable will not be > introduced that is shorter than this variable "cType"? It does not matter if a newer variable will be introduced with a shorter name as long as cType is shorter than customer. There is no interference with other variables. > Question: If your code is ever maintained by some one else can you > guarantee that some one doesn't come along and say... "cType" is a > poorly named variable... let me expand that to "customerType"... oops > that just broke your action bean... sure you could plaster comment > warnings all over the place but guess what this happens... I can't. I inserted a warning comment to make people aware of the reason why I called this variable cType instead of customerType. > It's great that Ben and Aaron assisted in helping you resolve this > offline and as such I am not sure what caveats and disclaimers they > attached to your following this approach (which I imagine there were > some or plenty)... . Though personally I think framework Developers > should discourage their user community from relying on such specific > implementation details of the framework especially when it depends on > something as fluid as length of a variable name. Well, it was not quite that offline, but IRC instead. They said something similar to "I don't think that this will be changed in future versions". > > Why? Because there are alternative solutions that although not as > direct that are more robust and should be prefered. For example: > > One important realization is that as far as the action bean is concerned > the type it sees from the JSP is of the abstract superclass when setting > any attributes or calling methods. The only time it deals with the > specific subclass is in the setter of of the customer type. Well how about: > > 1) Creating a simple helper object that extends Customer called say > CustomerDetails except you also add to it: > a) a CustomerType attribute > b) a method with the following signature that simply examines the > customer type attribute that it has internally, constructs the > appropriate subclass and populates it with the attributes it has internally: > public Customer createCustomer() > > 2) (Optional) Make the CustomerDetails class package private and put it > in the same package as its action ean > > 3) Having Stripes deal with and populate this CustomerDetails object > which is an attribute retained by the action bean > > 4) In your event handler methods methods simply do to get the > appropriate customer object to perform further processing e.g. data > access, service call, etc...: > Customer customer = this.getCustomerDetails.createCustomer(); > > What is the downside: > > - Well you are instantiating an additional intermediary object i.e. you > are not dealing directly with the end object Yes. This adds complexity because I need to keep the CustomerDetails object in sync with the other customer objects. > > What is the upside: > > - It eliminates having code that has a side effect in a setter which > goes against best practices (for me personally) > - It is agnostic of how Stripes is implemented internally "today" and > "tomorrow" (barring major revision framework changes of course) > - It eliminates having to incorporate disclaimer / banner comments on > NOT changing cType and not making ANY other variable shorter than this > cType variable > - It does not sacrifice readability of the variable (as per your choice > to use cType) > - The code that determines the type and creates the appropriate subclass > is encapsulated in the helper object > > In the end, everyone can decide what makes sense for them but IFF anyone > chooses to adopt the strategy you propose as a solution then I would > strongly encourage above and beyond banner comments et al. having at > least 1 Unit Test case that specifically tests for and ensures that the > "side effect" is not broken in the future. Very nice idea that did not occur to me. But I still think that it is not perfect either due to the added complexity. > > HTH, > > --Nikolaos > Thomas ------------------------------------------------------------------------------ This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first _______________________________________________ Stripes-users mailing list Stripes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/stripes-users