Discussions

News: Struts Live Chapter: Nested POJOs

  1. Struts Live Chapter: Nested POJOs (51 messages)

    The new chapter will include a solution to one of the most frequently heard complaints about Struts: that it doesn't provide a simple way to meaningfully nest POJO graphs in ActionForms. The provided example code solves this problem and includes an integrated solution for automating conversion, formatting, and validation.

    Check out Struts Live Chapter: Nested POJOs

    Threaded Messages (51)

  2. Struts Live Chapter: Nested POJOs[ Go to top ]

    Useful for developers that are initimately familiar with Struts, but without the code samples the chapter is hardly worth downloading. Also, the apparent complexity of the solution high-lights yet another problem with struts, there aren't enough extension points to plug in custom solutions. Anybody that has looked through the code of the request processor and request utils will probably agree that they have made it quite hard to plugin a new form loader for example without extending several struts classes.

    And the great MVC framework continues :(

    PS Took a (good) look at JSF recently and was also disappointed at the (very) poor JSP integration. So disappointing that they would do so much to make things easier and then break down at the final fence, getting designers to write front-end code and not java developers that really understand the different contexts available.
  3. Struts Extensibility[ Go to top ]

    I completely agree regarding your comments on Struts extensibility, or lack thereof. We've been working on the successor to RequestProcessor dubbed struts-chain, which applies a Chain of Resposibility pattern to request processing. This should make it easy to have complete control over how Struts operates without extending any classes.

    Don

    [disclaimer: I am a Struts committer]
  4. Souce Code for Chapter 10[ Go to top ]

    Useful for developers that are initimately familiar with Struts, but without the code samples the chapter is hardly worth downloading.

    If you read the chapter you will notice a linke to:

    Struts Live Project

    You will find links to the example source in the files section.

    I do think that the chpater cuts short of explaining the solutions.

    Oz
  5. This is too much work![ Go to top ]

    Somehow I get th feeling we are trying to fit a square peg in a round hole.
  6. This is too much work![ Go to top ]

    Somehow I get th feeling we are trying to fit a square peg in a round hole.

    I'm thinking I might agree. I'm not sure if this is easier than simply doing your own conversions (even if, as the article states, you must perform them twice - 1x in validation, 2nd to map to POJO). But maybe it is easier this way - I'd like to play with it but I downloaded the src code and the .war example file it mentions was not in the distribution. I'd like to see the struts and JSP files.

    Mike
  7. This is too much work![ Go to top ]

    I do believe this is a lot of work too. Writing conversion may be for every class to work with Struts doesn't seem reasonable. Because one of these lacking feature, i am back to square evaluation other MVCs.
  8. Square peg in a round hole seems correct, since the author seems to be misusing the framework. He wants a place to cache values as they are transfered and validated, and wants the conversion to happen during this time. Struts is not written to work that way. The ActionForm *is* the cache, which is why you use Strings there, and you do the conversion to the final POJO destination *after* the data is validated, since you already know that the POJO can accept the values from the request.

    The author says "Developers are then burdened with implementing any conversion, formatting, and population code needed to transfer values to and from the buffer to their destination." Well, that's not entirely accurate, because that's what BeanUtils is for. Once you have validated the user's input, you use BeanUtils to populate your POJO with the values from your ActionForm.
  9. Re: Too much work...[ Go to top ]

    Struts is not written to work that way.

    Correct. From my point of view, that's a design flaw that is, fortunately, correctable.

    > The ActionForm *is* the cache, which is why you use Strings there, and you do the conversion to the final POJO destination *after* the data is validated, since you already know that the POJO can accept the values from the request.

    What would be the point of validating values that can't be converted? Isn't a conversion failure by definition a validation failure?

    >Once you have validated the user's input, you use BeanUtils to populate your POJO with the values from your ActionForm.

    As I point out in the chapter, which is only partially reproduced here unfortunately (the complete chapter is over 40 pages), BeanUtils doesn't handle conversion errors (nor could it, since it has no knowledge of the ActionForm or the request, and therefore couldn't post meaningful error messages, or preserve user entered form values that are in error). This forces an extra layer of validation which in turn just creates more meaningless drudge work for developers, and also requires dual maintenance.
  10. Re: Too much work...[ Go to top ]

    What would be the point of validating values that can't be converted? Isn't a conversion failure by definition a validation failure?

    Exactly. And that's why you validate first before you convert. As part of the validation, you should verify that the values can be converted correctly.

    > BeanUtils doesn't handle conversion errors (nor could it, since it has no knowledge of the ActionForm or the request, and therefore couldn't post meaningful error messages, or preserve user entered form values that are in error).

    AFAIK, it's not designed to. It seems you're focusing on BeanUtils at a point where you shouldn't.

    1) Request is submitted to the server
    2) Struts uses BeanUtils to populate ActionForm containing String fields
    3) ActionForm validates user input.
    4) Action receives validated ActionForm
    5) Action uses BeanUtils to copy ActionForm values onto POJO

    You're trying to do step 5 during step 2, and you're using data types in your ActionForm that can't accomodate invalid values. That's why it becomes difficult.
  11. Re: Too much work...[ Go to top ]

    And that's why you validate first before you convert. As part of the validation, you should verify that the values can be converted correctly.

    My point is that the simplest (and most accurate) way to validate that a value can be converted is by attempting the actual conversion. If the conversion succeeds, then the value can be bound to its target property. If not, an appropriate error message can be posted, and the erroneous input value can be cached for redisplay.

    Since it is actually quite easy for the framework to do this automatically, why not do it at the framework level? In several years of experience using this approach on large-scale enterprise applications, I haven't seen a downside. On the other hand, the gain in developer productivity (not to mention morale) and ease of maintenance was quite dramatic.

    >You're trying to do step 5 during step 2, and you're using data types in your ActionForm that can't accomodate invalid values. That's why it becomes difficult.

    But it's not difficult! That's exactly my point. Here's the equivalent of the five steps you described in a StrutsLive ActionForm (PojoActionForm):

    1) Request is submitted to the server (Same)

    2) PojoActionForm uses PropertyUtils to populate itself, including any nested beans. Conversion errors are trapped and appropriate error messages posted to the request, and the original input values are cached for redisplay.

    (All functionality provided automatically by framework)

    3) PojoActionForm performs any additional values, such as range checks, required fields, length, regex, etc.

    (Validations applied automatically based based on declarative specification. Custom validations can be written as usual)

    4) Action receives validated PojoActionForm

    5) Step 5? There is no step 5. :-)

    Turns out this requires a lot less code in most cases, and cuts down on dual maintenance. Unless you're writing really tiny apps, this saves time and money, and allows developers a lot more flexibility, while still preserving the standard default Struts functionality for regular ActionForm subclasses.
  12. But it's not that easy is it?[ Go to top ]

    But it's not quite that easy is it? You still have to customize the RequestProcessor. You now have to use custom tags, right, to get the String input value for display? Unless I am missing something, the latter consequence is enough to keep me from going this route.

    Why not have a generic DynaBean type ActionForm that acts as a display/input value cache, and give it the capability to bind to/from a domain object, applying conversion using standard PropertyEditors? This approach seems to work OK, although one limitation I've found with Struts is it poor support for nested properties in form beans.

    Keith
  13. Re: But it's not that easy is it?[ Go to top ]

    But it's not quite that easy is it? You still have to customize the RequestProcessor.

    Is that so hard? Since the 1.1 release, Struts has made the RequestProcessor class configurable through a setting in struts-config.xml, implying an expectation that it would be customized.

    Still, I take your point (and the point about it being a good bit of work, which was raised by several earlier posters). That's the reason I started the StrutsLive project (http://strutslive.dev.java.net). A number of developers I've spoken to have expressed keen interest in taking advantage of this type of functionality, but can neither afford the time, nor to take on the potential project risk and maintenance issues themselves.

    While the StrutsLive codebase is in its infancy, I think it already serves as a decent proof-of-concept that can serve as a starting point for building a custom framework, and upcoming enhancements over the course of the next few months should make it a solid alternative as a drop-in enhancement for real-world development projects.

    >You now have to use custom tags, right, to get the String input value for display?

    Nope. Request values that fail conversion are cached in the ActionForm. A few lines of code in an overridden version of PropertyUtilsBean.getProperty() takes care of retrieving the cached values (if present), as well as invoking any needed formatting functionality. Formatters are selected based on the property type (default), or on the property path (overrides the default, if any).

    >Why not have a generic DynaBean type ActionForm that acts as a display/input value cache, and give it the capability to bind to/from a domain object, applying conversion using standard PropertyEditors?

    I like that approach a lot, and I've used it extensively (though using simple Formatters rather than PropertyEditors, which seem to me to impose some additional complexity without adding a whole bunch of value). To be honest, it proved to be an excellent solution for us, but it required writing a fairly sophisticated (read expensive) custom binding mechanism.

    I was drawn to the StrutsLive approach because it's a lightweight way of achieving many of the benefits of the DynaBean approach at a significantly lower cost.

    Jonathan
  14. Re: Too much work...[ Go to top ]

    I see your points, thanks. I actually just coded up a implementation of this pattern using Spring's ServletRequestDataBinder (and thus it's BeanWrapper and standard PropertyEditor machinery) and it works nicely!

    I do have a question for you though: how are you handling reference data (e.g drop-down) request-scope population on form binding/valiation error? With your RequestProcessor forwarding back to the input forward like it does -- there doesn't seem an elegant solution.

    Keith
  15. Hi,

    I have used Strutslive code in my project and ran into the exact same issue that u mentioned in your post ie the loss of request scope ref data values used for populating pulldowns whenever an validation/conversion error occurred.

    We have a workaround now. What we have done is split our action into 2 actions. One action "loads" the ref data values by setting them as attributes of the request. This action is not mapped to a formbean. (mapping this action to a formbean would mean that the framework automatically steps in and tries to populate the formbean before transferring control to the action). This action after loading the ref values forwards to the second action.

    The second action is responsible for loading the actual data (non ref-values) for the jsp page and also for saving the submitted data. This action is mapped to a formbean. When the jsp is submitted, before invoking this second action, the framework attempts to do type conversion and populate the formbean. If it fails it invokes the action specified in the input attribute for this action, which is action#1. This
    has worked for me.

    Probably there might be a better/more elegant solution.
  16. Using custom tags might be another alternative. The collection of beans used for populating the pulldowns could be generated by the custom tag handlers.
  17. Hi Prabhakar - sorry for the delayed reply.

    >Using custom tags might be another alternative. The collection of beans used for populating the pulldowns could be generated by the custom tag handlers.

    True, but I wouldn't go to the trouble of creating custom tags unless they provided other benefits. Basically, any form of lazy initialization would get the job done, so as I indicated earlier, you could do this just as easily in ActionForm accessor methods. The idea is that instead of 'pushing' the values into the request in an Action, you let the JSP tags 'pull' the values from the ActionForm by accessing a getter method.

    You could implement the getter to retrieve the values if they aren't already cached (assuming that caching is appropriate, i.e., that the values don't need to be refetched on each request). That, of course, raises the question of where the cache is located. If you have a session-scoped form, you could cache the values locally. Another option would be to cache them in a class (you can use a Map keyed by HttpSession if value lists are unique per user).

    If you want to make things a bit more elegant, you could create a class whose instances contain the reference values. If these are simple label-value pairs, the class could define a list of beans containing the label-value pairs, and its list property could then be plugged straight in to an html:options tag. The class could take care of caching the values and performing lazy initialization.

    You could then create ActionForm properties containing instances of this class or its subclasses, and reference the value lists directly as property attributes in your JSP tags.
  18. Re: Too much work...[ Go to top ]

    ... the simplest (and most accurate) way to validate ... is by attempting the actual conversion. ... [if it fails] an appropriate error message can be posted, and the erroneous input value can be cached for redisplay.

    How about this as a non-invasive solution. Re-implement a version of BeanUtilsBean.copyProperties(...) that returns null or an ErrorMessages containing each conversion that failed. If not null (conversion errors) you simply 'this.addErrors(...)' and 'return mapping.getInputForward();'.

    Thoughts?

     - Jason B.
  19. Testing - Please disregard[ Go to top ]

    Testing - Please disregard
  20. Re: Too much work...[ Go to top ]

    While you are at it, you could also have a version that doesn't actually copy anything, just checks the conversions. (Say against a Class instead of an instance) Call this in the form bean's validate method and you have automatically done a whole set of verifications automatically.
     - Jason B.
  21. Re: Too much work...[ Go to top ]

    While you are at it, you could also have a version that doesn't actually copy anything, just checks the conversions.

    Sure, but wouldn't you end up having to call the same code again to populate the beans? Once you've coerced the request values to the required types, why not go ahead and populate the properties?

    It always seemed wasteful to me to do a bunch of conversions and discard the converted values, and then do the same set of conversions later to populate an object graph that was already avaialable when the first round of conversions was done. To make matters worse, I've observed that all too often, apps that take this approach don't even leverage the code base used to performed the initial conversions. The net result is incurring the downsides of dual maintenance and increased risk (not to mention tedium) without any discernable offsetting benefits.
  22. Re: Too much work...[ Go to top ]

    I completely agree with you on that. IF, and its a big if, I did something like this it would be quickly rewritten to emulate 'conversion' but actually use the commons validators. Personally, having conversion based validation errors come from the actual conversion would work for 95% of the time. If I needed anything else (multi-page form w/o conversion until later step) it could be done through manual validations.
     - Jason B.
  23. Re: Too much work...[ Go to top ]

    I completely agree with you on that. IF, and its a big if, I did something like this it would be quickly rewritten to emulate 'conversion' but actually use the commons validators.
     
    That sounds like a workable approach. So are you planning to make API calls to the Validator framework from within your validate() method?

    >Personally, having conversion based validation errors come from the actual conversion would work for 95% of the time.

    Yep. It's a great way of eliminating a lot of tedious grunt work that every Struts app would otherwise have to deal with.
  24. Re: Too much work...[ Go to top ]

    How about this as a non-invasive solution. Re-implement a version of BeanUtilsBean.copyProperties(...) that returns null or an ErrorMessages containing each conversion that failed

    Hm, I might need a little more context here. If you mean subclassing BeanUtilsBean and then registering the subclass with BeanUtils, you'd have a problem in that copyProperties() is typed as void, so you can't get it to return anything unfortunately. As to using ErrorMessages in BeanUtilsBean, that sets up a circular dependency (Struts depends on BeanUtils, which would then depend on Struts), the consequences of which are usually pretty icky, so you probably want to avoid doing that.

    Also, don't forget that you will need to cache request parameter values couldn't be converted so that they can be presented back to the user interface. The tricky part is that they need to be presented by tags that are bound to properties of the ActionForm, so you need a way to get in front of the call to getProperty() in order to replace the form values with the request values on a case-by-case basis. (This is one way of doing it; another way would be to create a custom ActionForm base class that implements DynaBean, which allows a lot of flexibility in terms of how you implement the get() method, among other things. I've actually done a closed source implementation using this approach that worked out extremely well -- but then I had a team of 8 developers to work on it. Oh well. :-).

    > If not null (conversion errors) you simply 'this.addErrors(...)' and 'return mapping.getInputForward();'

    You will probably still want to execute any other validations that don't depend on properties for which conversion failed. Otherwise the UI behavior gets pretty strange. Say I have only one conversion error on a form, but three other values are invalid. The app only displays the conversion error message, so I fix that value and submit the form.

    When the page redisplays, that field is okay, but I now have three error messages on those other fields (the ones containing values that failed validation, but not conversion). Say I try to fix the first of these, but fat-finger in a value that fails conversion. Now I get a conversion error on that field, but the other two validation errors go away. Now I fix the conversion error, and...uh, oh well, you get the idea. :-)

    Aside from all this though, one of the issues with using BeanUtils this way from my perspective is the inadequacy of the ConvertUtils design, which to my way of thinking has several drawbacks:

    1. It's focused solely on converting inbound values in a way that makes it useless for formatting outbound values, which is the other half of the conversion equation.

    2. The API is too restrictive; the Converters have no context, so there's no way to customize their behavior on a property-by-property, or per-request basis.

    3. (This is fairly related to 2) There's no way to specify String-to-String conversions, so for example I can't write a PhoneNumberConverter and bind it to a String property (without binding all Strings to PhoneNumberConverter). That forces me to create custom value classes for things like PhoneNumber, rather than just configuring the binding somewhere.

    I'm probably forgetting something, but the lack of registration by property (not easily fixable), and the lack of formatting facilties are huge issues to me. That's the reason I went with the Formatter approach, and having used it extensively on large development projects, it still amazes me that such a small, simple feature could pay such rich dividends in by dramatically simplifying web app development and maintenance.
  25. Re: Too much work...[ Go to top ]

    Sorry, I didn't give you enough context as to what type the Form fields are. And you are totally right about the 'half validation' problem, unless you include the second idea from our other thread. To pull it all together...

     -1 ActionForm with all String variables.
     -2 New 'Target Type Validation Method' method to do automatic validation based on a target DAO (validates against target DAO property types). Ignores null source values.
     -3 Modified BeanUtilBean.copyProperties() that returns ActionErrors if there are any conversion problems. (It should never happen, but if does it's better to know than to lose data w/ default values). Ignores null source values.


    #1 In case of validation errors, we don't lose the user's input.
    #2 Automates tedious simple type based validations.
    #3 Returns ActionErrors, because I hate things 'just happening' like default values being set...


    The idea here is you could have a CustomerForm object with all String variables. CustomerDAO with various variable types. CustomerForm.validate() calls #2 'TargetType Validation Method' which validates any set values for conversion to the DAO object, then any other more specific validations. CustomerAction calls #3 'Modified copyProperties' which will notify in the now unlikely case there is a conversion problem.

    Why ignore null values? In case you only want to use part of the Form object. (...say on the edit name page of the edit customer area.) This way the absense of a corresponding HTML form field will not wipe out data in your Data object. Still not sure if this is the best way...

     - Jason B.
  26. Re: Too much work...[ Go to top ]

    To pull it all together... -1 ActionForm with all String variables. -2 New 'Target Type Validation Method' method to do automatic validation based on a target DAO (validates against target DAO property types). Ignores null source values. -3 Modified BeanUtilBean.copyProperties() that returns ActionErrors if there are any conversion problems. (It should never happen, but if does it's better to know than to lose data w/ default values). Ignores null source values.

    Hm, sounds a bit like FormDef, but they use custom validation code instead of commons-validator. They also provide a way to handle nested objects, but it requires specifying an XML mapping for each nested property. From a quick browse of their CVS repository it looks like pretty solid code, and there's nice beginner documentation plus some Javadoc.

    Were you considering providing support for nested, mapped, and/or indexed properties? From your remarks I'm inferring that a flat ActionForm is sufficient for the type of stuff you need to do, but correct me if I'm wrong.

    Regarding null values, I'm not sure if you'd be able to get away with ignoring them since most web apps need to provide a way for users to blank out fields in the UI, and that's usually transmitted as a null parameter value in the request.

    > In case of validation errors, we don't lose the user's input.

    StrutsLive takes care of this by caching the values in a Map during it's populate() method, so there's never a need to create (or maintain) String fields or XML mappings for DAO properties exposed in the UI.

    > Automates tedious simple type based validations.

    StrutsLive automates formatting of DAO values during response processing as well. You may want to consider doing something along those lines as well if you have time.

    > CustomerAction calls #3 'Modified copyProperties' which will notify in the now unlikely case there is a conversion problem.

    Note that you'll have to create subclasses of the existing Converters, as that's the only way to change their behavior, as noted in the following excerpt from the ConvertUtilsBean Javadoc:
    ...
     * For backwards compatibility, the standard Converters for primitive
     * types (and the corresponding wrapper classes) return a defined
     * default value when a conversion error occurs. If you prefer to have a
     * {@link ConversionException} thrown instead, replace the standard Converter
     * instances with instances created with the zero-arguments constructor. For
     * example, to cause the Converters for integers to throw an exception on
     * conversion errors, you could do this:
     *
     * // No-args constructor gets the version that throws exceptions
     * Converter myConverter =
     * new org.apache.commons.beanutils.converter.IntegerConverter();
     * ConvertUtils.register(myConverter, Integer.TYPE); // Native type
     * ConvertUtils.register(myConverter, Integer.class); // Wrapper class
    ...
  27. Re: Too much work...[ Go to top ]

    Regarding null values, I'm not sure if you'd be able to get away with ignoring them since most web apps need to provide a way for users to blank out fields in the UI, and that's usually transmitted as a null parameter value in the request.

    Unless I'm off my rocker, a blank text field transmits an empty String which would be copied over. The only exception is Checkboxes, which are a pain anyway you look at them. Essentially, on a submission that you know has checkboxes in it, the form's reset method you would set those properties to false. On submission, any that are checked will be set to true.
    Were you considering providing support for nested, mapped, and/or indexed properties? From your remarks I'm inferring that a flat ActionForm is sufficient for the type of stuff you need to do, but correct me if I'm wrong.

    Anything that worked with BeanUtilBean.copyProperties(...) should work, since I only modified/added to their code.


    I'm a little new to struts and so, until I have the time to evaluated extensions such as StrutsLive this is my way of quickly getting where I need to be. It also sticks within the 'standard' struts way of doing things, which is good if I need to hand this off to another person.

    I need to:
     - Do quick conversion based validations
     - Copy properties Form -> DAO without getting:
       - Any surprises in default values from failed conversions
       - Surprises from unset form fields overwriting good data

    StrutsLive seems to do MUCH more than I am attempting here. I hope it will fill my needs, in a few months, when the application I am working on move out of its 'prototype' phase.

    If anyone wants a copy of my sloppy code, just ask.

     - Jason B.

    PS: Yes my validateStrutsProperties(...) does validate by attempting conversions, which is wasteful. However, it was quick to implement, it works, and can be transparently reworked for performance later. Its interesting to note that the apache validator source validates using conversions and catching Exceptions! I'll have to implement improved versions later...
  28. Re: Too much work...[ Go to top ]

    Unless I'm off my rocker, a blank text field transmits an empty String which would be copied over.

    Unfortunately, in the current state of affairs that's entirely browser dependent, and different browsers do different (and sometimes even silly) things.

    > Anything that worked with BeanUtilBean.copyProperties(...) should work, since I only modified/added to their code.

    Right, but since you said that your ActionForm properties would be typed as String, that would imply no nesting. So if an Employee DAO contained an instance of Address, you could model that by either flattening all the needed fields on the ActionForm, or by creating an Adress bean (or ActionForm for that matter), and nesting it in the EmployeeActionForm.

    The copyProperties() method does a shallow copy, so the nested values would be missed. As long as you don't plan to use nested objects in your ActionForms you should be just fine.

    >StrutsLive seems to do MUCH more than I am attempting here. I hope it will fill my needs, in a few months, when the application I am working on move out of its 'prototype' phase.

    That sounds like a wise decision. I wouldn't recommend developers becoming early adopters of StrutsLive (at least not for an important project) without having had some hands-on Struts experience. Plus, a few months down the road some of the kinks in StrutsLive should be ironed out, plus there will be significant new features that I'm hoping people will find compelling.

    > Yes my validateStrutsProperties(...) does validate by attempting conversions, which is wasteful.

    Yes, but not to a degree that would be likely to have a performance impact, so when I said that it seems wasteful to throw away the converted value during validation and perform the conversion again (in a different codebase) during population, I meant wasteful from a design perspective. I'm a big fan of the DRY (Don't Repeat Yourself) principle, which says that when you notice that the design is doing the same thing in two or more places, it's probably time to refactor. :-)

    Anyway, best of luck with your prototype. It sounds like you're on the right track! - Jonathan
  29. Abbreviated chapter[ Go to top ]

    Jonathan is correct. The chapter here on TSS is only a partial chapter of what he has created for the Struts Live book. Our goal was not to do a bait and switch with regard to the chapter, but to give the community an idea of where Jonathan is taking the book, and introduce his project on java.net as well. We did not feel it was fair to the current subscriber base of Struts Live to post the entire book (as we did in May) as well as the first full chapter from Jonathan. Sorry for any confusion.
  30. Struts Live Chapter: Nested POJOs[ Go to top ]

    It seams that PojoRequestProcessor breaks Tiles.
    It should inherit from TilesRequestProcessor instead of RequestProcessor.

    - Tarik
  31. Struts Live Chapter: Nested POJOs[ Go to top ]

    It seams that PojoRequestProcessor breaks Tiles.It should inherit from TilesRequestProcessor instead of RequestProcessor.

    Tarik, thanks for reporting this. It's a priority 1 defect that will be fixed in a patch release planned for January 3rd. Here's part of the writeup from the issues tracker:
    This is actually a bug relating to back-compatability with Struts 1.1. Our overriden implementation of RequestProcessor.process() includes a call to processCachedMessages(), which is a 1.2 API. We can patch this for now by using reflection to invoke the method, but in the long term (probably the 0.3 release), we'll want to eliminate the overidden process() method entirely, as there's really no need for it.

    (It was done this way to make the example in the Struts Live book a little clearer, but was never intended to be the approach used by the framework.)

     (from http://strutslive.dev.java.net/issues/show_bug.cgi?id=1)
  32. Struts Live Chapter: Nested POJOs[ Go to top ]

    Tarik, thanks for reporting this. It's a priority 1 defect that will be fixed in a patch release planned for January 3rd.

    Er, okay, I guess it's January 5th already, and I still haven't cut the new release (sheesh). The good news is the coding is done, but I still need to do a bit more testing and documentation before pushing out the release. It should be out in the next day or two. On the plus side, I managed to put in significatly enhanced support for Collections, arrays, and primitives, the latter two of which are always a bit of a bugaboo in Java, with its funky type system.
  33. Tiles[ Go to top ]

    Hi Johnatan,

    Let me know when you have release ready and I'll look at it/test it. I'm also interested to see what have you done with collections.

    Did anyone attempt to create non-intrusive datagrid where the state of tuples/beans would be available (something like New, NewModified, NotModified, Deleted).
    I know that there is a ValueList and Struts-Layout but both requrire its own taglibs (i'd prefer to use Nested taglib) and in case of Struts-Layout javascript need be there and there is no support for all HTML elements.

    What i do now is use a "convention" where any gridable tuple/bean must have itemState which is then set on bean instantiation and using javascript when user updates/adds.

    I was thinking of approach where setting bean/tuple state would be done before setter is called e.g. getValue, compare old and new, set state and setVallue.
  34. Tiles[ Go to top ]

    Let me know when you have release ready and I'll look at it/test it.

    It's ready as of about 2:00 this morning :-) I really appreciate your offer to test it out. Please let me know if you run into any issues.

    >Did anyone attempt to create non-intrusive datagrid where the state of tuples/beans would be available (something like New, NewModified, NotModified, Deleted....What i do now is use a "convention" where any gridable tuple/bean must have itemState which is then set on bean instantiation and using javascript when user updates/adds.

    I'm planning to take a slightly different approach in StrutsLive. I'm working on a controller that manages the list displayed on the current page, which is backed by a second controller that manages the current list of fetched objects. The second controller collaborates with a well-defined persistence interface that provides access to the needed business services.

    The second controller caches the list of fetched objects, and creates a cloned list (containing references to the objects in the cached list) that it modifies in response to user actions (i.e., add and remove). During a save operation, the two lists can then be compared to determine which objects to insert or delete.

    I don't see a need for these components to handle creates, and they deal with bulk updates as a special case (the list components apply the bulk modifications, so they know which objects were changed). Of course good object-relational mapping frameworks such as Cayenne and Hibernate manage a great deal of this stuff themselves (i.e., knowing which objects have been added/deleted on a relationship, which fields have been updated, etc.), so if you can use one of those you're more than halfway home.

    > I was thinking of approach where setting bean/tuple state would be done before setter is called e.g. getValue, compare old and new, set state and setVallue.

    I don't know if you've looked at the Observer pattern, but that can also be a pretty decent way to deal with this, especially if you're using a (reasonably flexible) code generator for your DTOs, or, even better, if you're using an AOP framework. :-)
  35. what about using dynaforms?

    we're used to work with dynaform containing pojo (and nested pojos) with formatter, this works fine even with collection properties.
  36. My alternative[ Go to top ]

    Instead of nesting beans for datagrid and muti row updates, and using another bean for single row and another for displaytag I do this:

    BaseBean extends FormBean implments Collection { . . }

    This way same bean works as a single bean (with a diferent populate) as muti row CRUD and w/ DisplayTag.
    Much cleaner I think.

    I know a lot of people do nesting of beans or dynabeans and that seems as less elegant to me.

    Free videos, etc:
    http://wiki.apache.org/struts/StrutsTutorials



    .V
  37. Re: My alternative[ Go to top ]

    Instead of nesting beans for datagrid and muti row updates, and using another bean for single row and another for displaytag I do this:

    >BaseBean extends FormBean implments Collection { . . }

    That sounds like an interesting approach, but your writeup is a little too brief to give me much to go on. For example, how do you transfer values to/from BaseBean, and where does conversion/formatting take place?

    One of the things that makes StrutsLive so useful IMO is the degree to which it automates validation, conversion, error messaging, and population. I'm not sure if you're saying that BaseBean accomplishes all that. It's also not clear to me if BaseBean is used only for Collections or if it's more generic than that.

    Thanks,

    Jonathan
  38. Re: My alternative[ Go to top ]

    >Instead of nesting beans for datagrid and muti row updates, and using another bean for single row and another for displaytag I do this:>BaseBean extends FormBean implments Collection { . . }That sounds like an interesting approach, but your writeup is a little too brief to give me much to go on. For example, how do you transfer values to/from BaseBean, and where does conversion/formatting take place?

    http://sourceforge.net/projects/infonoia
    look at video and code here ("basicPortal")

    Basicaly the bean still has getters/setters, it just is able to iterate.

    (now I am working on a SoA version the is Map based so no need to write getters/setter. I never like DynaBeans)
    .V
  39. Struts Live Chapter: Nested POJOs[ Go to top ]

    Does MiddleGen, JAG, or XDoclet automate the display of nested POJOs?
  40. The real issue with POJO graphs?[ Go to top ]

    Isn't the real issue here that we have an impedance mismatch between Java object graphs and HTML forms?

    We can represent n-level data-centric Java object graphs. In addition, we can automate the population of any single node in the graph to/from an HTML form. That said, HTML does not support the notion of a nested, hierarchical, update-able forms.

    The same complexity that we find on the back end between our O/R layer and RDBMS exists on the front side between Java POJO graphs and HTML.

    Time to start building out Swing HTTP clients I imagine.

    This approach would revolutionize how Internet host systems communicate. In addition, it would increase the efficiency of network communication several fold.

    Benefits of Wide Scale Adoption:
    Save Energy
    Decrease Response Times
    Provide richer user Internet Experiences

    Just one road block...Java is currently in a Sun jail cell.

    Free Java!!!
  41. The real issue with POJO graphs?[ Go to top ]

    I agree with your overall point, but disagree about java being in a sun jail. Sun provide fine-grained APIs from which frameworks are built, they don't provide frameworks. But thats a conversation for a different thread.

    In terms of frameworks, struts continues to fall behind other MVC frameworks and is now several iterations behind the power and flexibility of webwork. It is also moving excruciatingly slowly and doesn't show any signs of catching up any time soon. Fortunately for the struts developers, almost all big companies have adopted it and aren't going to throw away their investment without good reason.

    I'd like to see the struts developers take a long look at the current architecture and at the architectures of the latest applications being developed and see what leasons could be learned. One of my gripes with struts is the lack of interceptors and also the closed nature of configuration. I'd prefer to use an IoC container to prepare my beans and then pass them to struts for request mapping. Also, it would be beneficial to remove the dependency on inheritence over interfaces, but I'm sure the struts developers are sick of hearing that.

    The biggest change I'd like to see is dropping actions, before you scoff and ignore my comment, let me continue! I think the webwork way of having the execute() method and validate() method in one class is much better than the struts approach of splitting the functionality across two classes. On my latest project I used Bob Lee's struts delegate and it reduced the amount of code we had to write and made the application easier to understand. The only problem is that we had to map the same action (as in pass the same value into the attribute) for every action even tho there was only one action in the whole application.

    I think you can guage the quality of a framework with one phrase (don't know where I heard this, credit to the author), a good framework is restrictive enough to force the correct pattern on you, but flexible enough that is doesn't impede you. I think struts fails in this regard but there is still too much room for developers to devise their own patterns which can be very different to another's.

    €0.02
  42. Drop form beans, not actions[ Go to top ]

    The biggest change I'd like to see is dropping actions, before you scoff and ignore my comment, let me continue! I think the webwork way of having the execute() method and validate() method in one class is much better than the struts approach of splitting the functionality across two classes.
    Totally agree, but I would drop form beans instead, and keep action classes. Let us see what form bean does.
    * Form bean has properties which are automatically populated by Struts when data is submitted. These properties are also used to display data in the JSP page. Well, Struts really sucks in population part. It calls property setters each time the action mapping is invoked. So forget about clean action chaining and clean redirection. If properties other than String or boolean (well, boolean have their quirks as well) then this automatic population does not work well anyway.

    So, request parameters can be read directly from HttpRequest and validated as needed. To show data on the page any plain javabean will do, so this function of a form bean can be worked around using standard servlet/JSP objects.

    * resetting fields. If you use values directly from the HttpRequest, why would you need this method?

    * validation. Again, this can be done in an action class on values from HttpRequest.

    So, form bean is a redundant class, that can be removed from the picture. Action class, on the other hand, is useful, because this is what recieves the control based on struts-config.xml mapping.
  43. I'd come to the same conclusions as the authors a couple of years ago and come to a similar conclusion.

    In fact, I've dvelopped yet another framework, "pompously" (is this an english word?) called "struts dataset", that quite elegantly answer concerns appearing in this post and more:

    - support for non String attributes
    - declarative validation (ala validator) and formatting of form attributes. Conversion failures are not
    - native support for collections and mass updates
    - state management that works best with session scope forms
    - support for pagination of collections
    and many more

    It has already been successfully used in some projects we have in my company.

    Maybe someone can tell me if this has been done a million time or if it has a chance to be wothwhile stuff for the community.
  44. dataset[ Go to top ]

    I would like to see it.

    (I did a collection version of it).

    Tell us on the struts list where you might post it.
    (or I can have a place for you to post it )
    .V
  45. dataset[ Go to top ]

    Well, it's part of closed source development (framework and toolbox for me company's java/J2EE/open source developments) and I must ask for an authorization to post it. I will try to get it.

    For now the only english documentation for it is the javadoc. We have a user manual, but it's only in French.

    If still interested, and if I can get the authorization, where precisely should I post it?
  46. dataset[ Go to top ]

    You can post it on apche web site for struts wiki
     http://wiki.apache.org/struts/StrutsTutorials

    Or on sandraSF.com you can join and ... submit a post, it shows up.

    .V
  47. Re: dataset[ Go to top ]

    Well, it's part of closed source development (framework and toolbox for me company's java/J2EE/open source developments) and I must ask for an authorization to post it.

    That would be great. Please don't get yourself in trouble with your company, though!

    > If still interested, and if I can get the authorization, where precisely should I post it?

    I think Vic's right, the Struts wiki would probably be a good place to post it. I'd happy to post it on StrutsLive for you if you'd prefer to limit the initial exposure. Anyway, I am very much looking forward to seeing it, and I hope you can get the needed authorization. If not, I would still be interested in comparing notes with you on features, techniques, etc.

    Jonathan
  48. Re: dataset[ Go to top ]

    I hope you can get the needed authorization. If not, I would still be interested in comparing notes with you on features, techniques, etc.

    If no authorization, this has to be limited so that it does not become plagarisam!

    Else, why pay sofware engineers rates when it's cheaper just to take other people's code and not even have attribution.

    .V
  49. Re: dataset[ Go to top ]

    I hope you can get the needed authorization. If not, I would still be interested in comparing notes with you on features, techniques, etc.

    >If no authorization, this has to be limited so that it does not become plagarisam!

    Actually, plagiarism is quite commonplace in software development, and is not illegal as long as no copyrights or patents are violated. Nevertheless, I have no interest in plagiarising anyone else's work; I'm mostly just curious to see which problems other developers have attempted to tackle, and whether they chose similar approaches in areas of overlap.
  50. I worked on a plugin that allows:

    - Standard form definition based on existing POJOs
    - Support for formatted conversion between forms and POJOs
    - Support for localized formats on submitted form values

    You can use it as light as you want, by just telling it to define action forms based on your POJOs (which is how it started), or as heavily as you want, by letting it perform the actual prepopulation of forms and parsing of submitted values.

    It'll support formatted values, such as 11,123.45, and localized formats as well, such as 11.123,45. Uses java.text classes for formatting and parsing.

    It generates action forms using standard Struts classes (DynaActionForm or any subclass you specify) and is compatible will standard Struts plugins such as Validator. A user has verified that it is also compatible with StrutsTestCase.

    http://formdef.dev.java.net/

    It's a good fit for CRUD-type operations, where your forms are more or less string-ified versions of business objects. You can use it to define your other DynaForms too, of course. In fact, there's an extension that you can use to combine form definition and form validation rules in one XML, so you don't have to switch between struts-config.xml and validation.xml.
  51. I'd come to the same conclusions as the authors a couple of years ago and come to a similar conclusion.In fact, I've dvelopped yet another framework, "pompously" (is this an english word?) called "struts dataset", that quite elegantly answer concerns appearing in this post and more:- support for non String attributes- declarative validation (ala validator) and formatting of form attributes.

    Excellent! Is any of this available as open source, or did you do this as part of a proprietary product? I'd love to take a look at it, if that's possible. StrutsLive is essentially an effort to rework in open source a more ambitious framework that I developed as part of a large, closed source project.

    > Maybe someone can tell me if this has been done a million time or if it has a chance to be wothwhile stuff for the community.

    That's a great question. I've been wondering that myself, and at every talk I've given, I've asked folks whether they had tried to implement or were aware of anything similar. So far the answer has always been "No," so I'm guessing that a there are quite a few developers who stand to benefit from the availability of a reasonable open source implementation.
  52. We had a situation where the top level UI was composed of a list of nested elements which in turn had another set of nested artifacts and another level after that. Thankfully we had the liberty of using DHTML as the specs were restricted to supporting a particular browser.

    The great thing about it was once you get a hang of using the struts nested tags, it really really simplifies the backend struts action class code. And all the data gets populated into the ActionForm object graphs just as you would expect. The downside is it requires a significant amount of jugglery in the client side javascript.
    DHTML is not suited for all projects, but where you can and make a conscious decision to use it, it could bring about a good deal of simplicity and also a great user experience.