Menu

Generic command for SimpleFormController?

2004-05-11
2004-05-11
  • Philip Fletcher

    Philip Fletcher - 2004-05-11

    This may be totally off beam as I'm fairly new to Spring/jsp, but is there any way of using a generic command object for SimpleFormController's formBackingObject?

    I've been trying to use a Map, but am running into difficulties (i.e. I'm stuck:) when trying to spring:bind  path="command.mapKey.value" within the jsp.

    I have a reasonable number of commands that do not map easily onto domain objects so would like to cut down the 'overheads'...

    BTW, I seem to be creating a minimum of 7 [m]vc files per domain object (add/update/view Controllers plus respective jsp's and validator). It's a fairly small app of about 40 domain objects - so will end up with > 280 vc object to maintain... eek! Is this normal?

    Philip

     
    • Ken Egervari

      Ken Egervari - 2004-05-11

      seriously, no real application could possibly use a generic one unless you gave it so many support methods to lookup and store values in it and create properties at runtime so they'll be set by spring.  Oh, and a lot of apps don't just store strings or longs.  I have ones that have arrays of this and that that behave differently, text fields that work with javasript editors that needed to be escaped and all kinds of weird stuff that it's sort of impossible to handle everything generically.  Just suck it up and make the form beans for each form.

       
    • Ken Egervari

      Ken Egervari - 2004-05-11

      "This may be totally off beam as I'm fairly new to I have a reasonable number of commands that do not map easily onto domain objects so would like to cut down the 'overheads'..."

      Of course.  Most complex forms actually modify list data, or modify data where a domain object has other contained domain objects that also need to be modifed on the same form.  For instance, for form wizards that have multiple pages, you can expect contained and list data to be added and modified - and yeah, it's a pain in the ass sometimes.

      "BTW, I seem to be creating a minimum of 7 [m]vc files per domain object (add/update/view Controllers plus respective jsp's and validator). It's a fairly small app of about 40 domain objects - so will end up with > 280 vc object to maintain... eek! Is this normal?"

      Adds and updates should be done on the same form, as all of my applications behave this way.  Just try and factor out the portions of code that need to be called for adds, for edits and for both.  You'll see that once you get the database storing domain objects using the same method for both updates and inserts (not very hard to do), then all you have to do is change the processing when the form is completed to handle those changes.

      For example, you should probably make formBackingObject() into a template method that looks like this (just as a simple example):

              if( this.isAnUpdate( request ) ) {
                  return this.doLoadFormBean( request );
              }

              return this.doCreateFormBean( request );

      Then, in controller subclasses, you just override those 3 methods.  The neat thing is that controllers don't have to worry about when they are called, but just how they should behave when they are called.  So for isAnUpdate(), you can just write a simple condition that tests a request attribute or something to see if the form is an update or add.  Sure it's simple, but that handles your problem.  You should do something similar when the form is processed.

      You can handle deletes in a generic way all across the application with something like this.  This assumes that idName, service and deleteMethodName have been defined as properties in the spring xml and that a request parameter has been passed with name of 'idName' (getIdParameter just cleans up RequestUtils.getParameter() for Longs).

      Long id = getIdParameter( request, idName );
              Class serviceClass = service.getClass();

              try {
                  Method deleteMethod =
                      serviceClass.getMethod( deleteMethodName, new Class[]{Long.class} );

                  deleteMethod.invoke( service, new Object[]{idValue} );
              } catch( NoSuchMethodException e ) {
                  throw new SimpleDeleteException( "There is no delete method called '" + deleteMethodName + "' in '" + service + "'" );
              } catch( IllegalAccessException e ) {
                  // do whatever
              } catch( InvocationTargetException e ) {
                  throw new SimpleDeleteException( e );
              }

      This is sort of application specific code, since it relies on Long's being the key to delete something out of the database and so on, but it works.  Reflection makes this possible.

      Just don't get into the habit of making a controller for each domain object, because somethings it's dumb to make all of this infrastructure for 2 fields of information.  Be creative and make the forms for usability, not for mindless coding pleasure.

       
    • Philip Fletcher

      Philip Fletcher - 2004-05-11

      No need for lots of support methods - take a look at org.springframework.beans.MutablePropertyValues - used during binding of request to command.

      Using this concept, I can validate the request before binding to the domain objects without having a request/command object for each and every route into the app...

       
      • Ken Egervari

        Ken Egervari - 2004-05-11

        You don't really get it.  A lot of what makes form beans hard to deal with is not defining strings and longs.  Even if there are 30 things on the form, that's still pretty easy to deal with, at least with IDEA anyway. 

        In some cases, if the domain object is simple, I'll just create a form bean class that extends the domain object and I won't have to do all that much extra.  In other cases, that's just not acceptable and you have to suck it up and define the form's fields exactly for performance and memory consumption reasons. 

        In any case, making a generic one, at least in the sense of a map, will only go so for and I'm not even sure if it's worth it considering the casting involved.  And in most real apps, as I said before, can be so complex that defining fields in a form bean (command class) should be the least of your worries.  For example, making a list of domain objects that also have contained objects map to html controls back and forth for both updates and inserts takes a bit of work.  Sure, you can generalize various aspects of it, but even with all the helper code in the world, it takes a few hours to get it working right whereas a simple 5-field form takes about 45 minutes to make the domain object, the validator, the views and controllers provided you have macros on the views and the appropriate helper classes to speed you along.

        I think people should be spending time on the mapping problem, where significant productivity can be seen rather than just avoiding making properties on command classes because that's not where experienced developers are spending their time anyway.

         
    • Philip Fletcher

      Philip Fletcher - 2004-05-11

      Thanks for this Ken - my forms (jsp's) are already merged for add/update - I'll have a go at refactoring my controllers next.

       

Log in to post a comment.