Eric
Take a look at the bottom save method 
HTH
Martin --

> I've been trying to get the hang of struts now for the past few months, and 
> am wondering how people write "re-usable" base classes for Struts.  If you 
> have the time, I'd really appreciate your thoughts on this - bear with me, as 
> it's a lot of reading:
> 
> My actions tend to be "similar" but making them "reusable" seems to be 
> eluding me.
> 
> What I would like to have is a set of reusable actions that handle the 
> following standard application features:
> 
> 1. A wizard (multiple jsps, one form bean, data formatting, validation 
> specific per page, with persistence when any navigation occurs, not just at 
> the end).  I've seen an example of an "at-the-end" wizard in the sample 
> Chapter from Struts Recipes by George Franciscus and Danilo Gurovich.
> 2. A multi-record screen ( one jsp, array of items, formatting of data, 
> validation w/ messages, and persistence)
> 
> Are these already written, so I can save some time?
> 
> So far, I've tried to write a re-usable piece of code for #2.
> Based on ideas in the ObjectSource Struts Survival Guide, Chapter 10:
> 
> #1: I wrote my own mapping.  Here are the properties:
> 
> public class CRUDActionMapping extends ActionMapping{
>   private String formType;
>   private String formMultiRecordProperty;
>   private String formDefConfig;
>   private String databaseBeanClassName;
>   private String saveServiceMethod;
>   private String retrieveServiceMethod;
>   private String serviceName;
>    
> #2: My struts-config.xml for the action for this class is defined as:
> 
>         <action path="/cbdeqr_engcodehours"
>                className="dep.ccdreporting.view.mappings.CRUDActionMapping"
>                
> type="dep.ccdreporting.view.actions.cbp.CbdeqrEngCodeHoursAction"
>                name="CbdeqrEngCodeHoursForm" 
>                input="/WEB-INF/jsp/cbp/cbdeqr_engcodehours.jsp"
>                scope="session"
>                validate="false"
>                parameter="event_save=save,event_codehours=initializePage,
>                event_reportInProgress=previous,event_countyHours=next,
>                default=unspecified">
>                <set-property property="cancellable" value="true"/>
>                <set-property property="formType" value="MultiRecord"/>
>                <set-property property="formMultiRecordProperty" 
> value="codehours"/>
>                <set-property property="formDefConfig" 
> value="CbdeqrEngCodeHoursForm"/>
>                <set-property property="databaseBeanClassName" 
> value="dep.ccdreporting.model.vo.cbp.CbdeqrCodeHours"/>
>                <set-property property="saveServiceMethod" 
> value="saveCbdeqrCodeHours"/>
>                <set-property property="retrieveServiceMethod" 
> value="getEngCodeHours"/>
>                <set-property property="serviceName" 
> value="dep.ccdreporting.model.service.cbp.CBPDaoService"/>
>                <forward name="hourspercounty" 
> path="/cbdeqr_engcountyhours.do"/>
>                <forward name="cbdeqr_main" path="/cbdeqr.do"/>
>                <forward name="success" 
> path="/WEB-INF/jsp/cbp/cbdeqr_engcodehours.jsp"/>
>        </action>
> 
> #3: The action class CbdeqrEngCodeHoursAction is reduced to two overridden 
> methods (save and initializePage, due to calling a calculation) of a base 
> class, and one method that gets the parameters to retrieve the data, which is:
> 
>   public HashMap getRetrieveServiceMethodParams( HttpServletRequest request ) 
> {
>       HttpSession session = request.getSession();
>       UserBean userbean = (UserBean) session.getAttribute("usrbean");
>       HashMap codeparams = new HashMap();
>       codeparams.put("report_id" , userbean.getReport_id()); 
>       return codeparams;
>   } // getRetrieveServiceMethodParams
> 
> #4: The base class handles the initialization of the page and the save.  
> Here's the save() call so this message doesn't get too wordy:
> 
public ActionForward save(ActionMapping mapping, 
                          ActionForm form, 
                          HttpServletRequest request, 
                          HttpServletResponse response) 
  throws Exception, 
         ServletException 
 {
/*   ActionForward fwd = mapping.getInputForward(); */
/*   if (isFormValid(mapping, form, request))  */
/*{ */
/*     if ( mapping instanceof CRUDActionMapping ) */
/* { */
/*         CRUDActionMapping myMapping = (CRUDActionMapping) mapping; */
/*         if (myMapping.getFormType().equalsIgnoreCase("MULTIRECORD"))  */
/*           {*/
            if(form.getAction() == 'save')
           {
             saveMultiRecordForm ( mapping, form, request );
             return(mapping.findForward("save"));
            }
            //return back ActionForward defined for keyword success
           return  (mapping.findForward("success"));
}
> and the save code -- this is where I'm confused - is this a reasonable 
> approach, or am I really missing the boat.  Specifically:  Should I be 
> creating the service like this?  Also, I really want the ability to log who 
> is performing the service methods as well - i.e. request.getRemoteUser(), so 
> do I have to pass this to the service method, or can I get it another way??
> 
> public void saveMultiRecordForm ( ActionMapping mapping,
>                                  ActionForm form,
>                                  HttpServletRequest request ) 
>   throws Exception
> {
>   // get all the action-mapping properties
>   CRUDActionMapping crudMapping = (CRUDActionMapping) mapping;
>   String formPropertyName = crudMapping.getFormMultiRecordProperty();
>   String formDefConfigName = crudMapping.getFormDefConfig();
>   String databaseBeanClass = crudMapping.getDatabaseBeanClassName();
>   String saveServiceMethodName = crudMapping.getSaveServiceMethod();
>   
>   // form-def returns an array of dynaActionForms, which is stored in the: 
> formPropertyName     
>   DynaActionForm dynaform = (DynaActionForm ) form;
>   ArrayList listOfFormDetails = (ArrayList) dynaform.get( formPropertyName );
> 
>   // db bean array needed for all our service method calls
>   Class classOfDbBean = Class.forName( databaseBeanClass );
>   Object[] details = (Object[]) Array.newInstance( classOfDbBean, 
> listOfFormDetails.size() );
> 
>   // Create an instance of the service class.
>   Class serviceClass = Class.forName( crudMapping.getServiceName() ); 
>   Object service = serviceClass.newInstance();
> 
>   // find the method that takes an array of data, and invoke it.
>   Object arguments[] = new Object[] { details };
>   Method svcMethod = serviceClass.getMethod(saveServiceMethodName, new 
> Class[] { details.getClass()} );
>   Object result = svcMethod.invoke( service, arguments );
> } // saveMultiRecordForm 
> 
> Thanks for anyone who has made it this far!
> 
> 
>

Reply via email to