Well, I'm gonna eat a bit of my own dog food!

I'm just starting on a project and I'm planing to use this kind of
controllers,one for SearchForms and other for CRUD.
I'd take it even a bit further and will try to guess most of the
configuration bits just from the command class name ...

I know that many of them will need customization but I think that
reimplementing referenceData, onBInd and createCommand will suffice for many
of them. 
One thing it's customizing one method and another thing is copy/paste older
controller and search/replace old command name, that is what I use to do
(not proud of it thought ;)

For now, after one week of working with them what I saw is that it can free
a lot of work, so you can encourage people to do better unit testing or use
css based forms instead of tables and ...

We are not using appfuse2 because we are tied to jdk1.4 so we are using a
mix-and-match of maven 2 and xdoclet, but appfuse is still a basic reference
:D

Regarding doing this for other frameworks, I think it basically depends on
how the framework manage to instantiate the command and set on it the
request parameters but it probably could be done, it's just a matter of look
at it

Cheers
Ivan



melinate wrote:
> 
> It really depends on what you are creating.  If you just need a simple 
> CRUD app and want to make it quickly, then this is pretty darn cool.  
> But as applications evolve and specifications change then these generic 
> classes are less applicable. I think it is a great idea to be able to 
> create a CRUD an AppFuse app with nearly no code--and then document how 
> to replace each generic class to add the specific functionality of the 
> business requirements.
> 
> Nathan
> 
> 
> Matt Raible wrote:
>> Thanks Ivan!  This looks like very useful code.  I'd definitely like
>> to have generic Controllers and views for all web frameworks in
>> AppFuse.  That way, you could add a POJO and have master/detail
>> screens w/o writing any code.
>>
>> FWIW... the project I'm currently working on has a similar
>> FormController.  The said they ended up customizing almost all their
>> forms and it's no longer used. Interesting, eh?
>>
>> Matt
>>
>> On 3/11/07, Ivan Garcia <[EMAIL PROTECTED]> wrote:
>>>
>>> With SpringMVC you can create generic based controllers ...
>>>
>>> you will need, though, to extend your persistent objects from a 
>>> common base
>>> class holding the id and a 'isNew' convenience method
>>>
>>> this can reduce to almost zero the amount of java code to create
>>> master/detail pages (which use to be a large part of most 
>>> applications ;-)
>>>
>>> Now if springmvc had something like webwork template based tags it 
>>> could be
>>> the killing web framework :D
>>>
>>> Hope it helps
>>>
>>> Regards
>>> Ivan
>>>
>>>
>>> ---------------- PersistentObject.java --------------------------------
>>> @MappedSuperclass
>>> public abstract class PersistentObject extends BaseObject {
>>>
>>>         protected Long id;
>>>         protected Integer version;
>>>
>>>         @Id  @GeneratedValue(strategy=GenerationType.AUTO)
>>>         public Long getId() {
>>>             return id;
>>>         }
>>>
>>>         @Version
>>>         public Integer getVersion() {
>>>             return version;
>>>         }
>>>
>>>         public void setId(Long id) {
>>>             this.id = id;
>>>         }
>>>
>>>         public void setVersion(Integer version) {
>>>             this.version = version;
>>>         }
>>>
>>>         @Transient
>>>         public boolean isNew() {
>>>                 return getId() == null;
>>>         }
>>>
>>> }
>>> ----------------------------------------------------------------------
>>>
>>>
>>> -------------- GenericFormController.java ----------------------
>>>
>>> import java.util.Locale;
>>>
>>> import javax.servlet.http.HttpServletRequest;
>>> import javax.servlet.http.HttpServletResponse;
>>>
>>> import org.apache.commons.lang.StringUtils;
>>> import org.appfuse.service.GenericManager;
>>> import org.appfuse.tutorial.model.PersistentObject;
>>> import org.appfuse.webapp.controller.BaseFormController;
>>> import org.springframework.validation.BindException;
>>> import org.springframework.web.servlet.ModelAndView;
>>>
>>> /**
>>>  * GenericFormController
>>>  *
>>>  * <p>
>>>  *  GenericFormController.java.html View Source
>>>  * </p>
>>>  *
>>>  * @author Ivan Garcia Sainz-Aja
>>>  *
>>>  */
>>> public class GenericFormController<T extends PersistentObject> extends
>>> BaseFormController {
>>>
>>>     private GenericManager<T,Long> manager = null;
>>>
>>>     /**
>>>      * Setter for the field manager
>>>      * @param manager The manager to set.
>>>      */
>>>     public void setManager(GenericManager<T,Long> manager) {
>>>         this.manager = manager;
>>>     }
>>>
>>>     /**
>>>      * Persists given perstistentObject using configured GenericManager.
>>>      * @param persistentObject
>>>      * @throws Exception
>>>      */
>>>     protected void doSave(PersistentObject persistentObject) throws
>>> Exception {
>>>         manager.save((T)persistentObject);
>>>     }
>>>
>>>     /**
>>>      * Removes the given persistentObject using configured 
>>> GenericManager.
>>>      * @param persistentObject
>>>      * @throws Exception
>>>      */
>>>     protected void doDelete(PersistentObject persistentObject) throws
>>> Exception {
>>>         manager.remove(persistentObject.getId());
>>>     }
>>>
>>>     /**
>>>      * @see
>>> org.springframework.web.servlet.mvc.SimpleFormController#onSubmit(javax.servlet.http.HttpServletRequest,
>>>  
>>>
>>> javax.servlet.http.HttpServletResponse, java.lang.Object,
>>> org.springframework.validation.BindException)
>>>      */
>>>     @Override
>>>     protected ModelAndView onSubmit(HttpServletRequest request,
>>> HttpServletResponse response, Object command, BindException errors) 
>>> throws
>>> Exception {
>>>         log.debug("entering 'onSubmit' method...");
>>>
>>>         PersistentObject persistentObject = (PersistentObject) command;
>>>         boolean isNew = persistentObject.isNew();
>>>         String success = getSuccessView();
>>>         Locale locale = request.getLocale();
>>>
>>>         if (request.getParameter("delete") != null) {
>>>             doDelete(persistentObject);
>>>             success = getViewAfterDelete();
>>>             saveMessage(request, getText(getCommandName() + 
>>> ".deleted", locale));
>>>         }
>>>         else{
>>>             doSave(persistentObject);
>>>             success = (isNew? getViewAfterInsert(): 
>>> getViewAfterUpdate());
>>>             String key = getCommandName() + ( (isNew) ? ".added" : 
>>> ".updated");
>>>             saveMessage(request, getText(key, locale));
>>>         }
>>>
>>>         return new ModelAndView(success, "id" , 
>>> persistentObject.getId());
>>>     }
>>>
>>>     /**
>>>      * @see
>>> org.springframework.web.servlet.mvc.AbstractFormController#formBackingObject(javax.servlet.http.HttpServletRequest)
>>>  
>>>
>>>      */
>>>     @Override
>>>     protected Object formBackingObject(HttpServletRequest request) 
>>> throws
>>> Exception {
>>>         String id = request.getParameter("id");
>>>         if (!StringUtils.isEmpty(id) && StringUtils.isNumeric(id)) {
>>>             return manager.get(new Long(id));
>>>         }
>>>
>>>         return createCommand();
>>>     }
>>>
>>>     //Configurable success views ...
>>>     private String viewAfterInsert;
>>>     private String viewAfterUpdate;
>>>     private String viewAfterDelete;
>>>
>>>     /**
>>>      * Returns the name of the view that should be shown on successful
>>> delete.
>>>      * Defaults to successView in case it is null.
>>>      * @return the viewAfterDelete
>>>      */
>>>     public String getViewAfterDelete() {
>>>         return (viewAfterDelete != null ? viewAfterDelete :
>>> getSuccessView()) ;
>>>     }
>>>
>>>     /**
>>>      * Returns the name of the view that should be shown on successful
>>> insert.
>>>      * Defaults to successView in case it is null.
>>>      * @return the viewAfterInsert
>>>      */
>>>     public String getViewAfterInsert() {
>>>         return (viewAfterInsert != null ? viewAfterInsert :
>>> getSuccessView()) ;
>>>     }
>>>
>>>     /**
>>>      * Returns the name of the view that should be shown on successful
>>> update.
>>>      * Defaults to successView in case it is null.
>>>      * @return the viewAfterUpdate
>>>      */
>>>     public String getViewAfterUpdate() {
>>>         return (viewAfterUpdate != null ? viewAfterUpdate :
>>> getSuccessView()) ;
>>>     }
>>>
>>>     /**
>>>      * @param viewAfterDelete the viewAfterDelete to set
>>>      */
>>>     public void setViewAfterDelete(String viewAfterDelete) {
>>>         this.viewAfterDelete = viewAfterDelete;
>>>     }
>>>
>>>     /**
>>>      * @param viewAfterInsert the viewAfterInsert to set
>>>      */
>>>     public void setViewAfterInsert(String viewAfterInsert) {
>>>         this.viewAfterInsert = viewAfterInsert;
>>>     }
>>>
>>>     /**
>>>      * @param viewAfterUpdate the viewAfterUpdate to set
>>>      */
>>>     public void setViewAfterUpdate(String viewAfterUpdate) {
>>>         this.viewAfterUpdate = viewAfterUpdate;
>>>     }
>>>
>>>
>>> }
>>> -------------------------------------------------------------------------- 
>>>
>>>
>>>
>>> --------------- dispatcher-servlet.xml -------------------------------
>>>
>>>     <bean id="personFormController"
>>> class="org.appfuse.tutorial.webapp.controller.GenericFormController">
>>>         <property name="commandName" value="person"/>
>>>         <property name="commandClass" 
>>> value="org.appfuse.tutorial.model.Person"
>>> />
>>>         <property name="validator" ref="beanValidator"/>
>>>         <property name="formView" value="personForm"/>
>>>         <property name="successView" value="redirect:persons.html"/>
>>>         <property name="cancelView" value="redirect:mainMenu.html"/>
>>>         <property name="manager" ref="personManager"/>
>>>     </bean>
>>>
>>> ------------------------------------------------------------------------- 
>>>
>>>
>>>
>>> obviously in real life you may need to override some methods 
>>> (referenceData,
>>> onBind ...) but you already have the bulk of the job done ;-)
>>>
>>> -- 
>>> View this message in context: 
>>> http://www.nabble.com/SpringMVC-can-do-Generic-Controllers-tf3385990s2369.html#a9425059
>>>  
>>>
>>> Sent from the AppFuse - User mailing list archive at Nabble.com.
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>> For additional commands, e-mail: [EMAIL PROTECTED]
>>>
>>>
>>
>>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 
> 

-- 
View this message in context: 
http://www.nabble.com/SpringMVC-can-do-Generic-Controllers-tf3385990s2369.html#a9927559
Sent from the AppFuse - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to