Hi folks, I've run into a problem with Struts 2 validation annotations.
In short -- I have a VisitorFieldValidator on an action POJO named ProductDetailAction. I have RequiredFieldValidator and RequiredStringValidator on one field within the "visited" object. Now -- ProductDetailAction did not (originally) inherit from ActionSupport. I could see validation errors cropping up in my log, but my save() method was still executing, because , as I understand it, without ActionSupport (or ValidationAware) there was no way for Struts to redirect my action back to my input() method when it found a validation error. If I change the hierarchy so that ProductDetailAction DOES inherit, indirectly, from ActionSupport, I can't even get to my input() method -- my productDetail JSP doesn't render. Instead I get the following exception: java.lang.IllegalArgumentException: The input() is not defined in action class $Proxy99 at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:412) at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:267) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:229) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:88) (...) I get the same exception if I simply implement ValidationAware in the same way that ActionSupport does. I'm including relevant snippets of ProductDetailAction, Product, and struts.xml below. Does anyone have any insight as to why this might be happening? I'm stumped, and so are my coworkers. Thanks. Jim ----- ProductDetailAction.java ----- @Validation public class ProductDetailAction extends FormularyDetailAction { // note: FormularyDetailAction extends ActionSupport // snippery @Override @SkipValidation public String input() throws Exception { if(id==null || id < 1) { this.product = new Product(); } else { this.product = formularyBso.fetchProduct(this.id); } return Action.INPUT; } @VisitorFieldValidator(message="") public Product getProduct() { return product; } // snippery } ----- Product.java ----- @Entity @Table(name="myrespironics.p_product_versions") @Validation public class Product extends FormularyProduct { //snip @RequiredFieldValidator(message="Please enter a value.") @RequiredStringValidator(message="Please enter a value.") public String getName() { return name; } //snip } ----- struts.xml ----- <struts> <package name="user" extends="struts-default"> <interceptors> <interceptor-stack name="myInterceptors"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="params"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare" /> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="myInterceptors"/> <global-results> <result name="error">/error.jsp</result> </global-results> <action name="productDetail" class="productDetailAction" method="input"> <result name="success" type="redirect-action">productList</result> <result name="input">/WEB-INF/secure/formulary/productDetail.jsp</result> <result name="success-subcategory" type="redirect-action"> <param name="actionName">subcategoryDetail</param> <param name="parse">true</param> <param name="id">${subcategoryId}</param> </result> </action> </package> </struts> -- Jim Kiley Technical Consultant | Summa [p] 412.258.3346 [m] 412.445.1729 http://www.summa-tech.com