Results 1 to 4 of 4

Thread: DefaultBeanValidator error

  1. #1
    Join Date
    Jun 2006
    Location
    Kansas City
    Posts
    95

    Question DefaultBeanValidator error

    I've been using the DefaultBeanValidator successfully for several months. Suddenly I am getting the following exception:

    Code:
    java.lang.IllegalArgumentException: Validator [class org.springmodules.validation.commons.DefaultBeanValidator] does not support [class com.silversky.scheduler.domain.Organization_$$_javassist_36] at org.springframework.validation.ValidationUtils.invokeValidator(ValidationUtils.java:60) at org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:395) at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:263) at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at
    It appears that my Organization domain class has been replaced by a javassist proxy which is not recognized by the DefaultBeanValidator. I wasn't aware that I was using javassist, but assume that it is buried deep inside Spring somewhere.

    I have not changed any of my validator configuration, but here is what I have:

    Spring configuration file:
    Code:
    	<bean id="validatorFactory"
    	      class="org.springmodules.validation.commons.DefaultValidatorFactory">
    	  <property name="validationConfigLocations">
    	    <list>
    	      <value>/WEB-INF/validator/validator-rules.xml</value>
    	      <value>/WEB-INF/validator/validation.xml</value>
    	    </list>
    	  </property>
    	</bean>
    	
    	<bean id="beanValidator" class="org.springmodules.validation.commons.DefaultBeanValidator">
    	  <property name="validatorFactory" ref="validatorFactory"/>
    	</bean>
    validation.xml:
    Code:
    <form-validation>
      <!--
        Define global validation config in validation-global.xml
      -->
      <formset>
          <form name="organization">
                  <field property="id"
                         depends="required">
    
                      <arg0 key="organization.id"/>
                  </field>
                  <field property="name"
                         depends="required">
    
                      <arg0 key="organization.name"/>
                  </field>
                  <field property="status"
                         depends="required">
    
                      <arg0 key="organization.status"/>
                  </field>
                  <field property="startDate"
                         depends="required">
    
                      <arg0 key="organization.startDate"/>
                  </field>
                  <field property="endDate"
                         depends="required">
    
                      <arg0 key="organization.endDate"/>
                  </field>
          </form>
    ...
    Should the domain object be replaced by the proxy like that, or is this a configuration problem?

  2. #2
    Join Date
    Jun 2006
    Location
    Kansas City
    Posts
    95

    Default

    It's been so long since I've worked on this, that I forgot that the validation.xml file is being generated in my Ant script by the xdoclet.modules.web.WebDocletTask from the @spring.validator annotations. So the question becomes, why isn't this particular domain class being picked up when others are? It has the same @spring.validator annotations as the other domain classes.

    I realize that there are newer ways to accomplish this, but I think I'm stuck with it because those annotations are used by my LabelTag to mark required fields on my forms. If there's a more modern way to accomplish all this without ripping the guts out of my web tier, I'm all ears.

  3. #3
    Join Date
    Jun 2006
    Location
    Kansas City
    Posts
    95

    Default

    OK, the WebDoclet task is working correctly. Here is the generated validation.xml entry for the class:

    Code:
          <form name="organization">
                  <field property="name"
                         depends="required">
                      <msg
                        name="required"
                        key="Name is required."
                        resource="false"/>
    
                      <arg0 key="organization.name"/>
                  </field>
                  <field property="status"
                         depends="required">
                      <msg
                        name="required"
                        key="Status is required."
                        resource="false"/>
    
                      <arg0 key="organization.status"/>
                  </field>
                  <field property="street1"
                         depends="required">
                      <msg
                        name="required"
                        key="Street is required."
                        resource="false"/>
    
                      <arg0 key="organization.street1"/>
                  </field>
                  <field property="city"
                         depends="required">
                      <msg
                        name="required"
                        key="City is required."
                        resource="false"/>
    
                      <arg0 key="organization.city"/>
                  </field>
                  <field property="state"
                         depends="required">
                      <msg
                        name="required"
                        key="State is required."
                        resource="false"/>
    
                      <arg0 key="organization.state"/>
                  </field>
                  <field property="postalCode"
                         depends="required">
                      <msg
                        name="required"
                        key="Postal code is required."
                        resource="false"/>
    
                      <arg0 key="organization.postalCode"/>
                  </field>
                  <field property="country"
                         depends="required">
                      <msg
                        name="required"
                        key="Country is required."
                        resource="false"/>
    
                      <arg0 key="organization.country"/>
                  </field>
                  <field property="phoneNumber"
                         depends="required">
                      <msg
                        name="required"
                        key="Phone number is required."
                        resource="false"/>
    
                      <arg0 key="organization.phoneNumber"/>
                  </field>
                  <field property="industry"
                         depends="required">
                      <msg
                        name="required"
                        key="Industry is required."
                        resource="false"/>
    
                      <arg0 key="organization.industry"/>
                  </field>
          </form>
    So the problem appears to be in the DefaultBeanValidator.

  4. #4
    Join Date
    Jun 2006
    Location
    Kansas City
    Posts
    95

    Thumbs up Solution

    I wrote my own version of DefaultBeanValidator to solve the problem. It's a hack, but it works with the proxy as well as the real domain classes.

    Code:
    public class SstDefaultBeanValidator extends AbstractBeanValidator {
    
        private Log logger = LogFactory.getLog( getClass() );
    
        /**
         * If <code>true</code> the full class name of each bean will be used as the form name when looking for
         * a <code>Validator</code>. If <code>false</code> the uncapitalized, short name of the class will be used.
         */
        private boolean useFullyQualifiedClassName = false;
    
        /**
         * Sets the value of the <code>useFullyQualifiedClassName</code>.
         */
        public void setUseFullyQualifiedClassName(boolean useFullyQualifiedClassName) {
            this.useFullyQualifiedClassName = useFullyQualifiedClassName;
        }
    
        /**
         * If <code>useFullyQualifiedClassName</code> is false (default value), this function returns a
         * string containing the uncapitalized, short name for the given class
         * (e.g. myBean for the class com.domain.test.MyBean). Otherwise, it  returns the value
         * returned by <code>Class.getName()</code>.
         * Modified to strip out proxy class name suffix.
         *
         * @param cls <code>Class</code> of the bean to be validated.
         * @return the bean name.
         */
        protected String getFormName(Class cls) {
        	String proxySuffix = "_$$";
        	String className = cls.getSimpleName();
        	String formName = className;
        	if (className.contains(proxySuffix)){
        		formName = className.substring(0, className.indexOf(proxySuffix));
        	}
        	
        	// decapitalize the form name
        	formName = formName.substring(0, 1).toLowerCase() + formName.substring(1);
        	
        	logger.debug("getFormName() className = " + className + " formName = " + formName);
        	
            return (this.useFullyQualifiedClassName) ? cls.getName() : formName;
        }
    
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •