Spring Framework
  1. Spring Framework
  2. SPR-7157

JSR-303 field-level constraints lead to error if no getter/setter available

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 3.0.2
    • Fix Version/s: None
    • Component/s: Core
    • Labels:
      None

      Description

      @Entity
      public class User extends BaseEntity {
      
              @NotEmpty
      	@Basic
      	private String _email;	
      
            //No java bean style getter setter
            
      	public String getEmail() {
      		return _email;
      	}
      
      	public void setEmail(String email) {
      		_email = email;
      	}        
      }
      

      The above code will cause the spring to through error

      Invalid property '_email' of bean class [org.ramanandi.matri.domain.model.User]: Bean property '_email' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
      
      Caused by:
      
      org.springframework.beans.NotReadablePropertyException: Invalid property '_email' of bean class [org.ramanandi.matri.domain.model.User]: Bean property '_email' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
      	at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:674)
      	at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:666)
      	at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:96)
      	at org.springframework.validation.AbstractBindingResult.rejectValue(AbstractBindingResult.java:103)
      	at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:79)
      	at org.springframework.validation.DataBinder.validate(DataBinder.java:692)
      	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:797)
      	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:349)
      	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:169)
      	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:421)
      	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:409)
      	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
      	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
      	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
      
      ................
      ...............
      

      As per the specification, Field level constraint should not need java bean style getters/setters and should be accessed using field access strategy

      See http://docs.jboss.org/hibernate/stable/validator/reference/en/html/validator-usingvalidator.html#d0e265

      When using field level constraints field access strategy is used to access the value to be validated. This means the instance variable directly independed of the access type.

      However spring forces me to have a pair of getter/setter.

        Activity

        Hide
        Sudhir nimavat added a comment -

        Spring should access the field using field access strategy instead of forcing to have a java bean style getter/setter

        Show
        Sudhir nimavat added a comment - Spring should access the field using field access strategy instead of forcing to have a java bean style getter/setter
        Hide
        Juergen Hoeller added a comment -

        After some investigation, this turns out to be a fundamental problem with DataBinder configuration: A Spring DataBinder is in bean property mode by default and can be switched to direct field access via an "initDirectFieldAccess()" call. Whatever you choose for your JSR-303 constraints needs to be compatible with the DataBinder configuration that you are using, since you are not performing JSR-303 validation on its own - you are rather using it within Spring data binding. So either use field names that match the getter/setter names, or switch your DataBinder to direct field access as well.

        Of course, no such constraint applies if you are performing native JSR-303 validation through injection of a javax.validation.Validator/ValidatorFactory: Calling the native JSR-303 validate method there will behave exactly as defined in the specification, with no additional access to the underlying field or property accessor.

        Keep in mind that, even with direct field access, the field name that you are using in your domain classes is also the name to use for referring to the field in your view. So unless you want to refer to "_email" field errors in your JSPs as well, I'd recommend using natural field names without additional underscores or the like in any case.

        As of Spring 3.0.3, we throw a clearer exception now in case of such misconfiguration, instead of the plain NotReadablePropertyException that you were getting. I hope that this helps a bit at least.

        Juergen

        Show
        Juergen Hoeller added a comment - After some investigation, this turns out to be a fundamental problem with DataBinder configuration: A Spring DataBinder is in bean property mode by default and can be switched to direct field access via an "initDirectFieldAccess()" call. Whatever you choose for your JSR-303 constraints needs to be compatible with the DataBinder configuration that you are using, since you are not performing JSR-303 validation on its own - you are rather using it within Spring data binding. So either use field names that match the getter/setter names, or switch your DataBinder to direct field access as well. Of course, no such constraint applies if you are performing native JSR-303 validation through injection of a javax.validation.Validator/ValidatorFactory: Calling the native JSR-303 validate method there will behave exactly as defined in the specification, with no additional access to the underlying field or property accessor. Keep in mind that, even with direct field access, the field name that you are using in your domain classes is also the name to use for referring to the field in your view. So unless you want to refer to "_email" field errors in your JSPs as well, I'd recommend using natural field names without additional underscores or the like in any case. As of Spring 3.0.3, we throw a clearer exception now in case of such misconfiguration, instead of the plain NotReadablePropertyException that you were getting. I hope that this helps a bit at least. Juergen
        Hide
        Hans Desmet added a comment -

        Talking about initdirectfieldacccess, another big improvoment would be if you could apply initdirectfieldaccess on nested objects of the command object.
        If you follow a Domain Driven Design, you make value objects immutable (no setters, attribute values come in as constructor parameters)
        You use these value objects often as members of entities.
        You cannot use such an entity as a command object of spring mvc, as the databinder doesn't support initdirectfieldacess on a nested property |-(
        (and the value object is a nested properties of the entity)

        Show
        Hans Desmet added a comment - Talking about initdirectfieldacccess, another big improvoment would be if you could apply initdirectfieldaccess on nested objects of the command object. If you follow a Domain Driven Design, you make value objects immutable (no setters, attribute values come in as constructor parameters) You use these value objects often as members of entities. You cannot use such an entity as a command object of spring mvc, as the databinder doesn't support initdirectfieldacess on a nested property |-( (and the value object is a nested properties of the entity)

          People

          • Assignee:
            Juergen Hoeller
            Reporter:
            Sudhir nimavat
            Last updater:
            Trevor Marshall
          • Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since last comment:
              3 years, 47 weeks, 6 days ago