<!-- --><style type="text/css">@import url(https://www.blogger.com/static/v1/v-css/navbar/3334278262-classic.css); div.b-mobile {display:none;} </style> </head><body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d7256432\x26blogName\x3dThe+Frustrated+Programmer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLACK\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://frustratedprogrammer.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://frustratedprogrammer.blogspot.com/\x26vt\x3d5012862196962223429', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
| Thursday, July 22, 2004

For some reason I'm always tempted to cram as much as I can into a single action definition in the struts-config.xml. Its mostly due to laziness. But I also like grouping related features together like CRUD (create, read, update, delete).

The thing about CRUD is, three of the four pieces (create, update and delete) can produce errors. This conflicts with my goal in two ways:

1 - You can only define validations for the form or the action.

Well, I tried to get around this. You may already know about the builtin 'page' attribute that Struts supports. If you pass 'page' as the name of a hidden parameter with an integer value, it will run all validations for that action/form with the page attribute less than or equal to the value of the 'page' parameter. This doesn't work because multiple validations could get run, when I only want one to get run.

Next I tried to configure validations on a per dispatch-method basis. I overrode my ActionForm's validate method:

public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {

ServletContext application = getServlet().getServletContext();
ActionErrors errors = new ActionErrors();

String validationKey = getValidationKey(mapping, request);

String suffix = (String) getMap().get("pageSuffix");
if (!StringUtils.isEmpty(suffix)) {
validationKey += '_' + suffix;

// Remove the suffix from the form in case this is a session scoped object.
getMap().remove("pageSuffix");
}

Validator validator = Resources.initValidator(validationKey,
this, application, request, errors, page);

try {
validatorResults = validator.validate();
} catch (ValidatorException e) {
log.error(e.getMessage(), e);
}

return errors;
}

This ran a validation matching the name of the form with the value of the 'pageSuffix' parameter appended to it. This ran the right validation but didn't work in the end because of reason #2.

2 - If the validation fails, the action can only have one input parameter to tell struts where to go.

This isn't good since delete() and add() will each want to go to a different page if an error occurs during validation. I think the next step is to configure the validator to allow for multiple forwards for the same form or action. Something like this would work, but I never implmented it because it still doesn't feel right.

<form name="fooForm_add" forward="addFailure">
<field property="name" depends="required" >
<arg0 key="label_name"/>
</field>
</form>


Well, if you can improve on it or tell me your preferred solution, I'll praise you in a comment. For now I will use a MappingDispatchAction (see my review) or a DispatchAction with at least two action definitions.