Discussions

News: Craig McClanahan comments on Struts Future, and Struts 1.2.4

  1. There has been lots of talk on where Struts fits in, after JavaServer Faces was born. There has been chat on the fact that it can "make JavaServer Faces easier to work with", and more.

    Craig McClanahan spoke a little on the future, in which he discusses the short term 1.3 release, and then the future of Struts in 2.0.

    Read more: Craig McClanahan on Struts

    NOTE: Where do you think Struts should go? What would you like to see in Struts 2.0?

    Also, Struts 1.2.4 has been released:
    Users of earlier versions of struts are strongly encouraged to move to the Struts 1.2.4 release after clean-compiling your application with deprecation warnings enabled. Struts 1.2.4 includes significant new functionality -- validator enhancements, a new standard DigestingPlugIn, a standard class: ModuleConfigVerifier, a new struts-config_1_2.dtd configuration DTD, new Taglib URIs, the possibility to use wildcards in your action-mappings, and much more.

    Download Apache Struts 1.2.4: http://struts.apache.org/download.cgi

    Read Struts 1.2.4 Release Notes:
    http://struts.apache.org/userGuide/release-notes.html

    Threaded Messages (45)

  2. http://cvs.apache.org/viewcvs.cgi/jakarta-struts/contrib/struts-chain

    .V
  3. In March in NYC at Vic's basebeans.com seminar I was talking to Ted Husted about Struts 2.0. He said they were probably going to break backward compatibility and look for new ideas. I suggested, jokingly, that they should build it on XWork, and, surprisingly, he didn't hate the idea... That's where I'd like to see Struts go :-)
  4. One thing I love from WebWork is the ability to have one Controller provide many actions. I know Struts is capable of doing this via the "parameter" attribute in the action-mapping node and subclassing a specialized Action class (I forget which specialization it is...there's a couple of different ones), but it's a little less sleek than how WebWork did it (IMHO). I believe WebWork2 had that functionality from the start; whereas, Struts added it in later (thus the less elegant Struts way).
  5. Ant+XDoclet do the magic[ Go to top ]

    One thing I love from WebWork is the ability to have one Controller provide many actions. I know Struts is capable of doing this via the "parameter" attribute in the action-mapping node and subclassing a specialized Action class (I forget which specialization it is...there's a couple of different ones), but it's a little less sleek than how WebWork did it (IMHO). I believe WebWork2 had that functionality from the start; whereas, Struts added it in later (thus the less elegant Struts way).
    We are about to opensource Struts Jumpstart project. Here is an example of real code from it. Action is doing many things and it is very maintanable and convenient IMO:
    Ant+XDoclet do the magic:

    package com.teamics.struts.jumpstart.web.usermgmt;

    import com.teamics.common.web.struts.action.AbstractAction;
    import com.teamics.common.util.DataHelper;
    import com.teamics.struts.jumpstart.bo.User;
    import com.teamics.struts.jumpstart.bo.ContactInfo;
    import com.teamics.struts.jumpstart.core.HibernateDAO;
    import com.teamics.struts.jumpstart.core.HibernateDAOFactory;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.ActionForm;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;

    /**
     * @struts.action path="/users/crud"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/read"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/new"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/newContact"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/delContact"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/upContact"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/downContact"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action path="/users/crud/delete"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     *
     * @struts.action-forward name="list" path="/do/users/list/refresh"
     * @struts.action-forward name="crud" path="/WEB-INF/user/userCRUD.jsp"
     */
    public class UserCRUDAction extends AbstractAction{

      public static final String ACT_CLOSE_CRUD = "closeCRUD";
      public static final String ACT_CONTACT_NEW = "newContact";
      public static final String ACT_CONTACT_DELETE = "delContact";
      public static final String ACT_CONTACT_UP = "upContact";
      public static final String ACT_CONTACT_DOWN = "downContact";

      HibernateDAO dao = ( HibernateDAO) HibernateDAOFactory.getSingletonOf( HibernateDAO.class );


      public ActionForward execute( ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response, HttpSession session ) throws Exception {

        String cmd = getActionCMD( request );
        String path = actionMapping.getPath();
        UserCRUDForm form = (UserCRUDForm) actionForm;

        if( ACT_CLOSE_CRUD.equals( cmd ) ){
          return actionMapping.findForward( "list" );
        } else if( path.endsWith( "read") ){
          String rn = form.getLogin();
          form.setUser( (User) dao.getObject( User.class, rn ) );
          form.setModeEdit();
        } else if ( ACT_DELETE.equals( cmd ) ){
          dao.deleteObject( form.getUser() );
          return actionMapping.findForward( "list" );
        } else if ( ACT_UPDATE.equals( cmd ) ){
          dao.updateObject( form.getUser() );
          return actionMapping.findForward( "list" );
        } else if ( ACT_NEW.equals( cmd ) || path.endsWith( "new")){
          User user = new User();
          user.setLogin( "newlogin");
          form.setUser( user );
          form.setModeNew();
          return actionMapping.findForward( "crud" );
        }else if ( ACT_CREATE.equals( cmd ) ){
          dao.saveObject( form.getUser() );
          return actionMapping.findForward( "list" );
        } else if ( ACT_CONTACT_NEW.equals( cmd ) || path.endsWith( ACT_CONTACT_NEW ) ){
          form.getUser().addContact( new ContactInfo( ContactInfo.PHONE, "000 999-0000")) ;
          return actionMapping.findForward( "crud" );
        } else if ( ACT_CONTACT_DELETE .equals( cmd ) || path.endsWith(ACT_CONTACT_DELETE) ){
          form.getUser().getContacts().remove( form.getIndex() );
          return actionMapping.findForward( "crud" );
        } else if ( ACT_CONTACT_UP.equals( cmd ) || path.endsWith(ACT_CONTACT_UP) ){
          DataHelper.up( form.getIndex(),form.getUser().getContacts() );
          return actionMapping.findForward( "crud" );
        } else if ( ACT_CONTACT_DOWN.equals( cmd ) || path.endsWith(ACT_CONTACT_DOWN) ){
          DataHelper.down( form.getIndex(), form.getUser().getContacts() );
          return actionMapping.findForward( "crud" );
        }

        return actionMapping.findForward( "crud" );
      }
    }
  6. Ant+XDoclet do the magic?[ Go to top ]

    Ant+XDoclet do the magic:
     ...
    /**
     * @struts.action path="/users/crud"
     * validate="false"
     * name="userCRUDForm"
     * attribute="userCRUDForm"
     * scope="session"
     ...
     * @struts.action-forward name="list" path="/do/users/list/refresh"
     * @struts.action-forward name="crud" path="/WEB-INF/user/userCRUD.jsp"
    I'm not sure I would want to keep these things in my action source code - what if I need to reuse the action for something else? Besides, wasn't it the whole point of having a separate struts-config.xml so we wouldn't have to hardcode the paths and stuff?
  7. Ant+XDoclet do the magic?[ Go to top ]

    Ant+XDoclet do the magic: .../** * @struts.action path="/users/crud" * validate="false" * name="userCRUDForm" * attribute="userCRUDForm" * scope="session" ... * @struts.action-forward name="list" path="/do/users/list/refresh" * @struts.action-forward name="crud" path="/WEB-INF/user/userCRUD.jsp"
    >>>I'm not sure I would want to keep these things in my action source code - what if I need to reuse the action for something else?
    - I never had a burnung desire to reuse an action because it is tiny layer I have to have to adapt my business layer to the web UI. Actions are dummy adapters ( kind of a proxy ) and logicless (almost)

    >>>Besides, wasn't it the whole point of having a separate struts-config.xml so we wouldn't have to hardcode the paths and stuff?
    I see struts config file mostly as a way to let Struts (Front Controller)to know about my classes. I am not sure it has much value as a level of indirection. Frankly I do not edit struts-config files manually for 3 years and pretty happy with "hardcoded" metainformation.
  8. Ant+XDoclet do the magic?[ Go to top ]

    In Struts framework an alternative to that long if will be delegating the if to struts config and have one action per operation which is not appealing to me solution at all.
    This is not true. One can use one DispatchAction and one action mapping to achieve the same. It would be a cleaner solution. To authorize a client one can call authorization from each method or create a simple guarding tag on the page.

    Another way is to use standard ForwardAction in action mappings, and put database access code into form beans. This works great for output operations. This way there is no need to define custom action class for each operation.
  9. Ant+XDoclet do the magic?[ Go to top ]

    This is not true. One can use one DispatchAction and one action mapping to achieve the same. It would be a cleaner solution.
    As long as Java Script is enabled on client. My code does not rely on JavaScript: We call getActionCommand( request ) method to extract command from parameter that matches pattern actionCMDnameOfAction.
    This way we simply have multiple submit buttong with names:
    name="actionCMDdelete"
    name="actionCMDupdate"
    name="actionCMDetc"
    To authorize a client one can call authorization from each method or create a simple guarding tag on the page.Another way is to use standard ForwardAction in action mappings, and put database access code into form beans. This works great for output operations. This way there is no need to define custom action class for each operation.
    I would not consider guardian tag on page as secure way because I can always type full get request and unwanted action will be executed. IMO guardian tag should be used in conjunction with "per method" guard ( nice case for AOP)
  10. Ant+XDoclet do the magic?[ Go to top ]

    This is not true. One can use one DispatchAction and one action mapping to achieve the same. It would be a cleaner solution.
    As long as Java Script is enabled on client. My code does not rely on JavaScript: We call getActionCommand( request ) method to extract command from parameter that matches pattern actionCMDnameOfAction.This way we simply have multiple submit buttong with names:name="actionCMDdelete"name="actionCMDupdate"name="actionCMDetc"
    Not really. You can either use links instead of posting a form, and supply method name in the URL. Or you can have hidden field called "method" and store method name in it. Anyway, it is the matter of preference.
  11. Ant+XDoclet do the magic?[ Go to top ]

    This is not true. One can use one DispatchAction and one action mapping to achieve the same. It would be a cleaner solution.
    As long as Java Script is enabled on client. My code does not rely on JavaScript: We call getActionCommand( request ) method to extract command from parameter that matches pattern actionCMDnameOfAction.This way we simply have multiple submit buttong with names:name="actionCMDdelete"name="actionCMDupdate"name="actionCMDetc"
    I developed a custom Action that takes the parameter in an action declaration and delegates to a method with same name as the parameter. It's very simple and has allowed me to use multiple public method in one single action file. No need to use huge if staments nor dependency on JavaScript. OTOH it requires you to declare an action for each method in struts-config.xml, so it tends to grow a lot. Although if you generate it via XDoclet, perhaps this is not so painful.

    Check in Struts 1.2.x the org.apache.struts.actions.MappingDispatchAction class, it does same thing.


    Cheers
  12. Re: Maintainable Struts Code[ Go to top ]

    Well, it's been a while since I've seen the Struts code (since we've moved all our projects to Tapestry). As far as I can tell, this example tries to limit what it does to event dispatching. All real operations are done outside action class (in DAO) which is a very good thing.

    Unfortunately, IMHO the code is not very readable nor maintainable. In fact, this long if/else chain looks like an anti-pattern to me.

    Just my $0.02.
  13. Re: Maintainable Struts Code[ Go to top ]

    Well, it's been a while since I've seen the Struts code (since we've moved all our projects to Tapestry). As far as I can tell, this example tries to limit what it does to event dispatching. All real operations are done outside action class (in DAO) which is a very good thing.Unfortunately, IMHO the code is not very readable nor maintainable. In fact, this long if/else chain looks like an anti-pattern to me.Just my $0.02.
    That _looks_ unmaintainable for me too :) but I get used to it and it is not that bad in practice. In Struts framework an alternative to that long if will be delegating the if to struts config and have one action per operation which is not appealing to me solution at all.
    I guess that my approach with simplified Action + XDoclet + use of nested taglib is as simple as we can get with Struts.

    Personally I prefer object and event oriented frameworks like Echo. Tapestry is nice but too HTML oriented IMO ( which is a good thing for today btw)
  14. Re: Maintainable Struts Code[ Go to top ]

    to Konstantin:
    My Struts Actions resemble to yours. I use if/else event dispatching too. I am evaluating Echo in present days. Echo appears to be a better choice for Intranet projects. It is really RAD web-apps framework. Have you any experience with Echo (any pitfalls) ?
  15. Re: Maintainable Struts Code[ Go to top ]

    to Konstantin:My Struts Actions resemble to yours. I use if/else event dispatching too. I am evaluating Echo in present days. Echo appears to be a better choice for Intranet projects. It is really RAD web-apps framework. Have you any experience with Echo (any pitfalls) ?
    I do not use Echo in any production environment because it is not quite crossbrowser - It (actuallu echPoint)did not work in Opera and not quite well in Mozilla 1.6 ( did not try IE). So I just LOVE its API and architecture and wait till implementation will be more browser friendly. It is sooo much better than Struts and JSF.
    But in the same time I would guess that pure Swing application(applet) can be better than Echo for Inet applications...
  16. Re: Maintainable Struts Code[ Go to top ]

    I've used it with Mozilla, IE and Opera. No problems. You might have been using a back level version. Checkout the Echo forums and the new releases of Echo and Echopoint.
  17. Re: Maintainable Struts Code[ Go to top ]

    I've used it with Mozilla, IE and Opera. No problems. You might have been using a back level version. Checkout the Echo forums and the new releases of Echo and Echopoint.
    Will certainly check it out. I played last with Echopoint couple months ago.
  18. Re: Maintainable Struts Code[ Go to top ]

    I've used it with Mozilla, IE and Opera. No problems. You might have been using a back level version. Checkout the Echo forums and the new releases of Echo and Echopoint.
    Will certainly check it out. I played last with Echopoint couple months ago.
    Not to Hijack this thread, but if you have any issues let 'em know. Todd and the rest are great at responding and fixing things.
  19. Re: Maintainable Struts Code[ Go to top ]

    I agreed that Echo is really a pretty elegant framework. It makes web-base programming like Swing or SWT/JFace, lots of Observer-Observerable pattern etc. and I think that is really nice. Glad to see that Echo is finally getting mentioned in TSS thread. I think Echo deserved much more serious attention cause it is really a great creation.

    regards
    tmjee
  20. Ant+XDoclet do the magic[ Go to top ]

    Here is an example of real code from it.
    >Action is doing many things and it is very
    > maintanable and convenient IMO

    Are you kidding ? This code is crap !

    How much longer will we have to endure the
    inventions by Craig McClanahan - Struts,
    JSF, what comes next... ?
  21. Ant+XDoclet do the magic[ Go to top ]

    >Here is an example of real code from it.>Action is doing many things and it is very> maintanable and convenient IMOAre you kidding ? This code is crap !How much longer will we have to endure theinventions by Craig McClanahan - Struts,JSF, what comes next... ?
    Well HTML code from DreamWeaver managed website looks like crap too, and yet it is quite maintainable and convenient from within DreamWeaver. My code requires use of Ant + XDoclet and nice IDE like IntelliJ.
    Definitely my code does not look good for notepad coders or from pure theoretical perspective.
  22. In March in NYC at Vic's basebeans.com seminar I was talking to Ted Husted about Struts 2.0. He said they were probably going to break backward compatibility and look for new ideas.
    I know Struts well enough to be comfortable with it and to do stuff I need. If the compatibility is broken, I would consider other frameworks as well like Spring. Will Struts 2.0 be so much better than Spring to justify moving to it, considering that apparently there are no new ideas yet? Struts is well-established product, why not just to keep it up-to-date and to enhance it with the goodies which are needed every day, instead of creating a whole new framework?
  23. Struts 2.0[ Go to top ]

    For 2.0, I would LOVE to see a stronger adherence to the KISS rule. In general, I find that when used "out of the box", Struts tends to encourage bloated code. I'm sure there's quite a number of people who would disagree, but just my experience after having used Struts for 3 years on several various projects.

    One thing I'd love to specifically see is the ability for the core framework to populate user entered values into domain object I specify and automatically display errors back to the user in instances of conversion failures (e.g. user entering "abc" for a year field). I just want to provide the format to use for dates, whole numbers, and decimal numbers. Struts would automatically know what pattern to use based on the domain property's data type.

    I've already written a thin layer around the Struts classes to do something along these lines. The simplified sequence of events is as follows:

    1. Call CustomBaseActionForm.populateFormData(Object bean). This introspects into the bean, reads all attributes (and sub attributes), converts them to a String value based on pre-defined set of conversion patterns I specify, and loads the values into an internally maintined Map.
    2. Forward to the JSP view.
    3. JSP view's custom tags pull the values using dot-notation. So I might refer to a value as "userObject.homeAddressObject.address1".
    4. JSP submits user data
    5. The CustomBaseActionForm has it's validate method invoked. It remembers from the "populateFormData" what data type each of the attributes are natively supposed to be, so it validates user entered data against that data type. Any conversion errors are fired here.
    5. By the time the Action.execute() method is invoked, the CustomBaseActionForm.populateBeanData(Object bean) can be invoked. This method pulls all the data from the CustomBaseActionForm's Map into the specified bean and all conversion is automatically performed. This can be confidently called because all data type validation has been automatically performed.

    More complex than that, but that's the basic order of events. In this situation, there's no duplicating of domain objects as ActionForms, no explicit data type validation, etc. The controller only has to worry about working w/ Objects and that's it. I would love to see this type of approach (Controllers only working w/ domain objects) embraced by Struts.

    Just my $0.02...would love to hear any thoughts!
  24. Struts 2.0[ Go to top ]

    For 2.0, I would LOVE to see a stronger adherence to the KISS rule. In general, I find that when used "out of the box", Struts tends to encourage bloated code. I'm sure there's quite a number of people who would disagree, but just my experience after having used Struts for 3 years on several various projects.One thing I'd love to specifically see is the ability for the core framework to populate user entered values into domain object I specify and automatically display errors back to the user in instances of conversion failures (e.g. user entering "abc" for a year field). I just want to provide the format to use for dates, whole numbers, and decimal numbers. Struts would automatically know what pattern to use based on the domain property's data type. I've already written a thin layer around the Struts classes to do something along these lines. The simplified sequence of events is as follows:1. Call CustomBaseActionForm.populateFormData(Object bean). This introspects into the bean, reads all attributes (and sub attributes), converts them to a String value based on pre-defined set of conversion patterns I specify, and loads the values into an internally maintined Map.2. Forward to the JSP view.3. JSP view's custom tags pull the values using dot-notation. So I might refer to a value as "userObject.homeAddressObject.address1". 4. JSP submits user data5. The CustomBaseActionForm has it's validate method invoked. It remembers from the "populateFormData" what data type each of the attributes are natively supposed to be, so it validates user entered data against that data type. Any conversion errors are fired here.5. By the time the Action.execute() method is invoked, the CustomBaseActionForm.populateBeanData(Object bean) can be invoked. This method pulls all the data from the CustomBaseActionForm's Map into the specified bean and all conversion is automatically performed. This can be confidently called because all data type validation has been automatically performed.More complex than that, but that's the basic order of events. In this situation, there's no duplicating of domain objects as ActionForms, no explicit data type validation, etc. The controller only has to worry about working w/ Objects and that's it. I would love to see this type of approach (Controllers only working w/ domain objects) embraced by Struts. Just my $0.02...would love to hear any thoughts!
    Hmmm... I thought Struts already did this for you and did the type conversion... Guess not. This is definitely powerful and useful in WebWork.
  25. Struts 2.0[ Go to top ]

    The only way (that I'm aware of) that the framework will do type validation for you is via the validator framework. I *think* (could be wrong here) that you have to specify in a validator mapping file the data type for each form's attribute (whether that be a DynaActionForm or an actual concrete ActionForm class). That's just too much configuration for me. I don't want to have to maintain an ActionForm class (which often mimics an existing domain class anyways which in turn has the data type information already) and then separately maintain what datatype that ActionForm's attribute is. I'm already pretty sick of all the various xml config files I have to deal w/ as it is.

    Could someone correct me if I'm wrong (that there is a way to do automatic data type validation/conversion in Struts)?
  26. Thank you Struts devs![ Go to top ]

    I just want to take a moment to thank the developers who have participated in creating Struts over the years. Open source devs rarely get the praise they deserve and I think these guys really deserve it. Struts certainly has saved me countless hours on projects over the 2.5 years that I've been using it. Of course, there's a few things I would like to see different but I feel that way about every product I use. :)

    Anyway, great job guys and keep up the good work!
  27. more configuration integration[ Go to top ]

    Agree.Just too many configuration file scatter around.
    I especially hate the validation file ,why not put together with form declaration just like this:

    <ActionForm name="Profile">
     <property name="name" type="java.lang.String" validate="notnull,max(30)"/>
     <property name="gender" type="java.lang.boolean"/>
     <property name="securityId" type="java.lang.String validate="regex(/d[15,18])"/>
    </ActionForm>

    I just want simply and clean config files.
  28. Unless I'm missing something your doing, you can set your DO on the form and use the dot notation from there. Nested works too, but no need to if you have the DO on the form. Plus all those form setters and getters are not required.

    If you are writing lots of custom validation you should look at the validator plugin, it will make things easier and cleaner.

    My forms are thin, my actions are thinner, and no code in JSP's.

    It works real nice!

    Good luck.
  29. Struts 2.0[ Go to top ]

    For 2.0, I would LOVE to see a stronger adherence to the KISS rule. In general, I find that when used "out of the box", Struts tends to encourage bloated code. I'm sure there's quite a number of people who would disagree, but just my experience after having used Struts for 3 years on several various projects.One thing I'd love to specifically see is the ability for the core framework to populate user entered values into domain object I specify and automatically display errors back to the user in instances of conversion failures (e.g. user entering "abc" for a year field). I just want to provide the format to use for dates, whole numbers, and decimal numbers. Struts would automatically know what pattern to use based on the domain property's data type. I've already written a thin layer around the Struts classes to do something along these lines.
     Populating the Domain Object from the FormBean/HttpRequest is a pain a redundant work.I do agree with you that there should be some mechanism which will do this , infact in my previous project we have done some sort of code generator code which would populate the DO from the HttpRequest.
    The simplified sequence of events is as follows:1. Call CustomBaseActionForm.populateFormData(Object bean). This introspects into the bean, reads all attributes (and sub attributes), converts them to a String value based on pre-defined set of conversion patterns I specify, and loads the values into an internally maintined Map.2. Forward to the JSP view.3. JSP view's custom tags pull the values using dot-notation. So I might refer to a value as "userObject.homeAddressObject.address1". 4. JSP submits user data5. The CustomBaseActionForm has it's validate method invoked. It remembers from the "populateFormData" what data type each of the attributes are natively supposed to be, so it validates user entered data against that data type. Any conversion errors are fired here.5. By the time the Action.execute() method is invoked, the CustomBaseActionForm.populateBeanData(Object bean) can be invoked. This method pulls all the data from the CustomBaseActionForm's Map into the specified bean and all conversion is automatically performed. This can be confidently called because all data type validation has been automatically performed.More complex than that, but that's the basic order of events. In this situation, there's no duplicating of domain objects as ActionForms, no explicit data type validation, etc. The controller only has to worry about working w/ Objects and that's it. I would love to see this type of approach (Controllers only working w/ domain objects) embraced by Struts. Just my $0.02...would love to hear any thoughts!
    Seems you had been inheriting from your Custom FormBean class which would have the populateFormData method.NOw in this approach I see the redundant work , you are populating the data from the FormBean as you could have done it from the HttpServletRequest in the Action class.The framework is populating the Data from the Httprequest to FormBean and then you are populating the data from the FormBean to DomainObject.
    Can't you use the Strut with the Dispatcher View Pattern , I mean dont use the FormBean in the flow where you dont require .This will definetly increase your development time but can have an impact on the performance where you are heavily relying on the Struts .Or your approach could be right but I dont have complete insights of your requirement .

    Regards
    Vicky
  30. Struts 2.0[ Go to top ]

    Populating the Domain Object from the FormBean/HttpRequest is a pain a redundant work.I do agree with you that there should be some mechanism which will do this ,
    There is: it is struts nested taglib.
    http://struts.apache.org/userGuide/struts-nested.html
    http://www.reumann.net/struts/nested.do
  31. Struts 2.0[ Go to top ]

    Regarding population of DO, I define a DynaValidatorForm and make the DO a form property as follows:

    <form-bean name="personForm"
                   type="org.apache.struts.validator.DynaValidatorForm">
          <form-property
            name="person"
            type="com.chrimbos.Person"/>
          
          ...

    </form-bean>

    The html request parameter names take the form of person.firstName, person.familyName etc and this then results in a populated DO (eg Person) accessable in the Action class. The validator plugin still works so you can define for example person.firstName is required.
  32. Struts 2.0[ Go to top ]

    The validator plugin still works so you can define for example person.firstName is required.
    I think of all the variations you can do automatic domain object population (using built in Struts components), the one you illustrated is probably the slimmest (thus best, IMO). However, it's still about a step or two away from where I want to be. The 2 things I dislike most is that I still have to create a custom ActionForm class and that I have to register the domain objects properties and data types w/ a validator config file (please correct me if I'm wrong on the 2nd point). I think defining your conversion patterns in the validator config file is great, but it should be able to automatically determine what conversion pattern(s) to use based on the datatype of the underlying property being set.
  33. Struts 2.0[ Go to top ]

    The 2 things I dislike most is that I still have to create a custom ActionForm class
    If you define a DynaValidatorForm in struts-config.xml you don't need to create a custom class - it also allows you to include other paramters/DOs that you want populated from the request but are not part of a particular DO.
    and that I have to register the domain objects properties and data types w/ a validator config file
    Struts will automatically determine required conversion pattern(s); you only need use the validator config file to validate values - ie not to map their type and so it is not mandatory. However Struts will fail silently and move on to the next property if you try to put for example "blahh" in an int value of the DO without proper validator configuration...
  34. Struts 2.0[ Go to top ]

    However Struts will fail silently and move on to the next property if you try to put for example "blahh" in an int value of the DO without proper validator configuration...
    Well, there u go....thats exactly why we say that Struts does not support automatic type conversion and somebody or the other keeps saying it does.
  35. Struts 2.0[ Go to top ]

    ... However Struts will fail silently and move on to the next property if you try to put for example "blahh" in an int value of the DO without proper validator configuration...
    Quite the opposite. This will call new Integer("blahh"), and if you have not configured an appropriate error page, your use will see an exception stack trace. As I've outlined above this can happen even if you have configured the validator, the user could always click the <html:cancel> button. For this reason most form beans get coded up with all properties as java.lang.String.

    What does happen sliently is the setting of properties that are missing in the target bean. It assumes that you did not want those properties copied. You may have a form bean that only has a subset of the properties of your data object.
  36. Struts 2.0[ Go to top ]

    Quite the opposite. This will call new Integer("blahh"), and if you have not configured an appropriate error page, your use will see an exception stack trace.
    This is not the behaviour that I see using Struts 1.1 with DynaValidatorForm. If I pass an empty or non numeric http parameter the value of the corresponding Integer property is an Integer with a 0 value. If no corresponding http parameter is passed the property has a null value.
  37. Struts 2.0[ Go to top ]

    Quite the opposite. This will call new Integer("blahh"), and if you have not configured an appropriate error page, your use will see an exception stack trace.
    Not true. BeanUtils uses a default set of converters (Integer, Float, etc) to do the conversion. The default behavior of the converters is to return the a preset default value whenever new Integer("some_string") throws an exception. You can override this behavior by register a different converter for each data type you want to override (see javadoc for org.apache.commons.beanutils.ConvertUtils).

    Currently, Struts does form population and form validation in two seperate steps in RequestProcessor. First, populate all form properties, with default type conversion if necessary. Second, perform form validation by calling form.validate(). IMHO, form population (thus, type conversion) and validation should be combined in one step: for each property, populate it with type conversion, then validate it if configured, save an error if either fails. In the end, if everything goes well, you have your bean populated with correct type and validated. Otherwise, you have an ActionError for each failed property. You can forward back to the input page with error messages. However, with the current implementation of commons.BeanUtils and commons.Validator, it's not an easy change.
  38. Nested tags do decouple, but...[ Go to top ]

    You're right, but the links aren't the obvious QED to the problem. It's not obvious for people that the nested tags decouple objects bound to the interface layer from the domain objects used in the business logic. Which they can very simply by nesting one level.

    After the one level of nesting, the objects don't know anything about Struts. I've made a few apps that have one central form bean that is only there to nest one level. All objects held inside that are plain objects with no Struts requirements.

    People also don't know how easy it is to get the inner objects populated and managed properly by the nested tags. This has always been the problem for the nested tags. Nobody can invision what they can really do from hello-worldish examples and complete hand holding.


    Arron.
  39. Nested tags do decouple, but...[ Go to top ]

    You're right, but the links aren't the obvious QED to the problem. It's not obvious for people that the nested tags decouple objects bound to the interface layer from the domain objects used in the business logic. Which they can very simply by nesting one level.Arron.
    OK, there is the exact place from where I have learned magic of "nested"
    http://www.keyboardmonkey.com/StrutMonkey/MonkeyStruts_v2.jsp
    http://www.keyboardmonkey.com/StrutMonkey/MonkeyStruts.jsp
    http://www.keyboardmonkey.com/
  40. Struts 2.0[ Go to top ]

    I just want to provide the format to use for dates, whole numbers, and decimal numbers. Struts would automatically know what pattern to use based on the domain property's data type. I've already written a thin layer around the Struts classes to do something along these lines. The simplified sequence of events is as follows:1. Call CustomBaseActionForm.populateFormData(Object bean). This introspects into the bean, reads all attributes (and sub attributes), converts them to a String value based on pre-defined set of conversion patterns I specify, ...
    I'm not sure I follow all off this, but you can certainly have Struts do some of your own type conversions. Although it is not as friendly as I'd like.

    I have managed to get Struts to convert all java.util.Date form bean properties to and from strings using the company format (dd/MMM/yyyy). Actually it is the commons bean utils that does this for you (http://jakarta.apache.org/commons/beanutils/api/index.html). You need to implement org.apache.commons.beanutils.Converter to convert your type to a String. You then register your converter with ConverterUtils (probably chaining in the original converter for some of the functionality). You need to register one to convert Strings to your type.

    One of the tricky bits is getting your converters registered with ConverterUtils at start up. You can do this by implementing org.apache.struts.action.PlugIn , putting the code in the init() method and naming this class in your struts-config.xml using a plug-in element.

    Watch for this gotcha. If you use the validator, then when the user clicks the cancel button, struts will try to still convert the strings submitted by the browser into values in your form bean without passing them through any validation. I guess it assumes that the action may send the user back to the same JSP form displaying the user entered values. So your converter should probably handle this. Although if you have ever cancelled a form with Integer (or other non-String) properties on the bean bean, you will have probably seen the resulting exceptions that are thrown by the default implementations.

    Now if you want automatic validation by type then I'm afraid I can't help.
  41. Stop wasting inheritance[ Go to top ]

    With a language that does not support multiple inheritance, Struts is very intrusive : all user defined actions must extend Action and all user defined form beans must extend ActionForm.
    Wouldn't interfaces or reflection provide the same functionnalities, without such intrusivity in user code ?
    Besides, it naturally leads to a surprising OO design : put the state into a class, put the logic into another one.
  42. Stop wasting inheritance[ Go to top ]

    With a language that does not support multiple inheritance, Struts is very intrusive : all user defined actions must extend Action and all user defined form beans must extend ActionForm.Wouldn't interfaces or reflection provide the same functionnalities, without such intrusivity in user code ?Besides, it naturally leads to a surprising OO design : put the state into a class, put the logic into another one.
    That's actually what's been bothering me for the past few years living in J2EE - not only Struts, almost all the frameworks, including EJB, lead to data/logic-separated designs by promoting various stateless logic encapsulation schemes, which makes a lot of J2EE web apps look a lot like cgi dressed up in Java.
  43. Stop wasting inheritance[ Go to top ]

    With a language that does not support multiple inheritance, Struts is very intrusive : all user defined actions must extend Action and all user defined form beans must extend ActionForm.Wouldn't interfaces or reflection provide the same functionnalities, without such intrusivity in user code ?Besides, it naturally leads to a surprising OO design : put the state into a class, put the logic into another one.
    That's actually what's been bothering me for the past few years living in J2EE - not only Struts, almost all the frameworks, including EJB, lead to data/logic-separated designs by promoting various stateless logic encapsulation schemes, which makes a lot of J2EE web apps look a lot like cgi dressed up in Java.
    It has been bothering a lot of us. I posted this question in response to Allen Holub's articles Why Getter and Setter Methods Are Evil and More on getters and setters. When it comes to the crunch: we have objects which have different methods in different parts of a distributed system. Presentation out on the client, business logic in the AppServer, persistence in the DAO. So we just ship around the state in value objects, and shovel the properties from one class to another using XDoclet and BeanUtil.copyProperties().

    It doesn't have to be this way. I did spend sometime exploring a pattern where an abstract class holding the properties is extended to implement the methods for the different environments, and to produce data transfer objects. A constructor for the abstract class would be the only thing required to transfer the properties between instances of the class. This sort of pulled back encapsulation. It also allowed the same technique to be used for the properties of the class, and so you could have GUI class where each property had it's own GUI class. However, it all falls down because most of the environments you need to use, dictate that your classes extend framework classes.
  44. Stop wasting inheritance[ Go to top ]

    With a language that does not support multiple inheritance, Struts is very intrusive : all user defined actions must extend Action and all user defined form beans must extend ActionForm.Wouldn't interfaces or reflection provide the same functionnalities, without such intrusivity in user code ?Besides, it naturally leads to a surprising OO design : put the state into a class, put the logic into another one.
    I'd say Struts is as intrusive as you allow it to be. For me an action class is just a place where I put my business/persistence calls, and a form bean is just a transport for request/response data. Struts does not require to implement domain objects using action classes/form beans.

    One can make do with one form bean only storing a javabean in a form bean's field. Then just access the business data using nested properties. Struts does not require to put everything that has to be displayed directly in a form bean.

    It the same way, the request can be read and processed manually, without having Struts to store input data in a form bean fields. Struts action mapping does not have to have a form bean.
  45. With Craig McClanahan acting as a Beehive mentor I'd like to see a closer harmony between Struts providing the underlying glue and Beehive addressing the simplicity of development. Beehive takes away a lot of the rough edges of Struts and improves developer productivity, coupled with eventual JSF integration and, eventually, a technological evolution of Tiles it's a good combination.
  46. A few suggestions for Struts 2.0[ Go to top ]

    - Integration into Portals using JSR-168. A good framework like Struts would be really nice to build complex portlets.
    - No more formbeans. The only case I can understand their use is when you want to repopulate data in an HTML form that didn't validate. There must be a better way than a dedicated class for this job.
    - If you keep the formbeans, rename the reset() method. Beginners with Struts don't understand how they're supposed to use it (they think they've to reset all the properties in their formbeans). In the renaming process, you could also rename some of the attributes in the struts-config to give them more explicit names. This file is really a pain to read, even when you're used to. It should be as clear as an Ant build file.
    - A better integration of all the web oriented projects at Apache (Struts, Velocity, Tapestry, Turbine, ... [add your favorite [incubating] one here]).

    Regards,
    Jean-Pol.