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