title: Spring, NotReadablePropertyException and Glassfish version
body: <p>I am working on a web-application that uses Spring MVC. </p>
  
  <p>It has been working fine on Glassfish 3.0.1, but when migrating to Glassfish 3.1, it started acting strange. Some pages are only partially showing, or showing nothing at all, and in the log, a lot of messages of this type:</p>
  
  <pre><code>    [#|2012-08-30T11:50:17.582+0200|WARNING|glassfish3.1|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=69;_ThreadName=Thread-1;|StandardWrapperValve[SpringServlet]: PWC1406: Servlet.service() for servlet SpringServlet threw exception
      org.springframework.beans.NotReadablePropertyException: Invalid property 'something' of bean class [com.something.Something]: Bean property 'something' 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:729)
          at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:576)
          at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:553)
          at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:719)
          at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:99)
          at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:226)
          at org.springframework.web.servlet.support.BindStatus.&lt;init&gt;(BindStatus.java:120)
          at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:178)
          at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:198)
          at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:164)
          at org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:127)
          at org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:421)
          at org.springframework.web.servlet.tags.form.TextareaTag.writeTagContent(TextareaTag.java:95)
          at org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102)
          at org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)
  </code></pre>
  
  <p>The error message isn't incorrect, because the property in question does not have a setter-method (gets its value through the constructor). But like I said, this has not been a problem when using Glassfish 3.0.1, only when using it on the new server with Glassfish 3.1.</p>
  
  <p>Does anyone know if there is something in the Glassfish version that might cause this? Or is it some kind of configuration that is missing on the new server?</p>
  
  <p>Some code:</p>
  
  <p>Controller:</p>
  
  <pre><code>@ModelAttribute
  public SomethingContainer retriveSomethingContainer(@PathVariable final long id {
      return somethingContainerDao.retrieveSomethingContainer(id);       
  }
  
  @InitBinder("somethingContainer")
  public void initBinderForSomething(final WebDataBinder binder) {
      binder.setAllowedFields(new String[] {
          "something.title",
          "something.description",
      });
  }
  </code></pre>
  
  <p>SomethingContainer:</p>
  
  <pre><code>@Embedded
  private final Something something = new Something();
  
  public Something getSomething() {
      return something;
  }
  //no setter
  
  public String getDescription() {
      return something.getDescription();
  }
  </code></pre>
  
  <p>Update:</p>
  
  <p>Restarting Glassfish actually removes the problem - temporarily. I suspect that it might have something to do with the loading of the custom binders, we had some problems with out of memory errors, which I thought had something to do with it, but that has been fixed without fixing this problem.</p>
  
  <p>Update 2:</p>
  
  <p>On the 3.0.1 server, the one of the jvm arguments was -client. On the 3.1-server, it was -server. We changed it to -client, and this made the frequency of the error go down a lot, it was happening every other day with -server, took 2 weeks for it to happen with -client.</p>
  
  <p>Update 3:</p>
  
  <p>Some information about the servers (more can be added if requested..)</p>
  
  <p>Server1 (the working one):</p>
  
  <pre><code>Windows Server 2003
  Java jdk 6 build 35
  Glassfish 3.0.1 build 22
  -xmx 1024m
  </code></pre>
  
  <p>Server2 (the one with problems):</p>
  
  <pre><code>Windows Server 2008 64-bit
  Java jdk 6 build 31
  Glassfish 3.1 build 43
  -xmx 1088m
  -xms 1088m
  </code></pre>
  
  <p>We are using Spring version 3.1.0.</p>
  
  <p>Update 4:</p>
  
  <p>I recreated the error by renaming a field in a jsp to something that does not exist in the modelattribute. </p>
  
  <p>But, more importantly, I noticed something: The fields where the system can't find the getters are often fields of superclasses of the ones that are referenced in the modelattribute. To continue my example, the SomthingContainer is really like this:</p>
  
  <pre><code>public class SuperSomethingContainer {
      [...]
      private Something something;
      public Something getSomething() {
          return something;
      }
  }
  
  public class SomethingContainer extends SuperSomethingContainer {
      [...]
  }
  </code></pre>
  
  <p>The reference in the controller stays as is, so it's referencing a field that is in the superclass of the object in question.</p>
  
  <p>Update 5:</p>
  
  <p>I tried connecting to the production server with a debugger after the error occured. I put a breakpoint on the return statement of a controller-method returning the object with the error, and tried to see if I could access the field with problems at the time. And that I could, so the problem must lie within Spring MVC/the generated jsp-classes.</p>
  
  <p>(Also, the field in error was of the type "someobject.something[0].somethingelse[0]", but when the somethingelse-list was empty, there was no error! To me, this implies that it somehow can't find the get-method of a list(?))</p>
  
  <p>Update 6:</p>
  
  <p>It seems that the problem has to do with the generation of Java-classes from the jsps. We have not used precompile jsps when deploying, so they are compiled when first used. The problem occurs the first time a page is visited, and the jsp compiled. I also noticed that once the problem has occured, jsps that are compiled after will all give errors. I've kept a few of the problem generated java files, and upon the next restart I will compare them to the working ones. Getting closer :)</p>
  
  <p>Update 7: </p>
  
  <p>Compared the compiled jsp java files that resulted in an error with ones that did not, and there was no difference. So that kinda leaves that out.</p>
  
  <p>So, I now know that the Java object leaving the controller is fine (checked with debugger),  and the java class generated from the jsp is fine. So it must be something in between, now I need to find out what...</p>
  
  <p>Update 8:</p>
  
  <p>Another round of debugging, and narrowed the problem down some more. It turns out that spring does some caching of the properties belonging to the various classes. In org.springframework.beans.BeanWrapperImpl, method getPropertyValue, there is the following:</p>
  
  <pre><code>private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException {
      String propertyName = tokens.canonicalName;
      String actualName = tokens.actualName;
      PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
      if (pd == null || pd.getReadMethod() == null) {
          throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
      }
  </code></pre>
  
  <p>The problem is that the cachedIntrospectionResults does not contain the property in question, it contains every other property of the class though. Will need to dig some more to try to find out why it is missing, if it's missing from the start or if it gets lost somewhere along the line.</p>
  
  <p>Also, I've noticed that the missing properties are those that do not have setters, only getters. And, it seems to be context aware, as indicated by the stacktrace. So not finding a property when visiting one page does not mean that its not available when visiting another.</p>
  
  <p>Update 9:</p>
  
  <p>Another day, more debugging. Actually found some good stuff. The getCachedIntrospectionResults() call in the previous code block wounded up calling CachedIntrospectionResults#forClass(theClassInQuestion). This returned a CachedIntrospectionResults object, containing far from all of the properties expected (11 of 21). Going into the forClass-method, I found:</p>
  
  <pre><code>static CachedIntrospectionResults forClass(Class beanClass) throws BeansException {
      CachedIntrospectionResults results;
      Object value = classCache.get(beanClass);
      if (value instanceof Reference) {
          Reference ref = (Reference) value;
          results = (CachedIntrospectionResults) ref.get();
      }
      else {
          results = (CachedIntrospectionResults) value;
      }
      if (results == null) {
      //build the CachedIntrospectionResults, store it in classCache and return it.
  </code></pre>
  
  <p>It turned out that the CachedIntrospectionResults returned was found by classCache.get(beanClass). So what was stored in the classCache was corrupted/did not contain all that it should. I put a breakpoint on the classCache.get(beanClass)-line, and tried running this through the debugger:</p>
  
  <blockquote>
    <p>classCache.put(beanClass, null);</p>
  </blockquote>
  
  <p>When allowing the method to finish, and rebuild the CachedIntrospectionResults, things started working again. So, what is being stored in the classCache is out of sync with what would and should be created if it was allowed to rebuild it. Whether this is due to something going wrong the first time it is built, or if the classCache is corrupted somewhere along the line I do not currently know.</p>
  
  <p>I'm starting to suspect that this has something to do with classloaders, as I've previously experienced problems due to changes in the way the classloader works when updating Glassfish..</p>