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! > > >