Spring, NotReadablePropertyException and Glassfish Version

I am working on a web application using Spring MVC.

It works great on Glassfish 3.0.1, but when it migrated to Glassfish 3.1 it started acting weird. Some pages are only partially displayed or nothing is displayed at all and there are many messages of this type in the journal:

[#|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.<init>(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) 

The error message is not erroneous, since this property does not have a setter method (gets its value through the constructor). But, as I said, this was not a problem when using Glassfish 3.0.1, only when using it on a new server with Glassfish 3.1.

Does anyone know if there is anything in the Glassfish version that can cause this? Or is it some kind of configuration missing on the new server?

Some codes:

Controller:

 @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", }); } 

SomethingContainer:

 @Embedded private final Something something = new Something(); public Something getSomething() { return something; } //no setter public String getDescription() { return something.getDescription(); } 

Update:

Restarting Glassfish actually fixes the problem - temporarily. I suspect this may have something to do with loading custom binders, we had problems with memory errors that I thought had something to do with it, but this was fixed without fixing this problem.

Update 2:

On server 3.0.1, one of the jvm arguments was -client. On server 3.1, it was a server. We changed it to -client, and this led to a significantly reduced error rate, which happened a day later with the server, and it took 2 weeks for this to happen with -client.

Update 3:

Some server information (more can be added on request ..)

Server1 (working):

 Windows Server 2003 Java jdk 6 build 35 Glassfish 3.0.1 build 22 -xmx 1024m 

Server2 (one who has problems):

 Windows Server 2008 64-bit Java jdk 6 build 31 Glassfish 3.1 build 43 -xmx 1088m -xms 1088m 

We are using Spring version 3.1.0.

Update 4:

I recreated the error by renaming the field in jsp to something that does not exist in the model attribute.

But, more importantly, I noticed something: fields in which the system cannot find getters are often areas of superclasses of those referenced in the model attribute. To continue my example, SomthingContainer really looks like this:

 public class SuperSomethingContainer { [...] private Something something; public Something getSomething() { return something; } } public class SomethingContainer extends SuperSomethingContainer { [...] } 

The link in the controller remains as it is, so it refers to the field that is in the superclass of the object in question.

Update 5:

I tried to connect to the server with a debugger after an error occurred. I set a breakpoint on the return statement of the controller method, which returns an object with an error, and tried to find out if I could access the problem field at that time. And that I could, so the problem should be in Spring MVC / generated jsp classes.

(In addition, the field with the error is of the type "someobject.something [0] .somethingelse [0]", but when some list was empty, there was no error! For me this means that it somehow cannot find get list method (?))

Update 6:

The problem seems to be related to the generation of Java classes from jsps. We did not use precompile jsps during deployment, so they were compiled on first use. The problem occurs when you first visit the page and compile jsp. I also noticed that as soon as the problem arose, jsps that compiled after all will give errors. I saved several problems with the java files being created, and after the next restart I will compare them with the working ones. Nearer:)

Update 7:

Compared compiled jsp java files that led to an error with those that did not, and there was no difference. Therefore, to prevent this from happening.

So now I know that the Java object leaving the controller is fine (checked with a debugger), and the java class generated from jsp is fine. So it should be something in between, now I need to find out that ...

Update 8:

Another round of debugging and narrowed down the problem a bit more. It turns out that Spring does some caching of properties belonging to different classes. In org.springframework.beans.BeanWrapperImpl, the getPropertyValue method has the following:

 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); } 

The problem is that cachedIntrospectionResults does not contain the corresponding property, but contains all the other properties of the class. It will be necessary to dig a little more to try to find out why it is absent, if it is absent from the very beginning or if it is lost somewhere along the line.

In addition, I noticed that the missing properties are those that do not have setters, but only getters. And it seems that this is contextually known, as indicated on the stack. Therefore, not finding a property when visiting one page does not mean that it is not available when visiting another.

Update 9:

Another day, more debugging. Actually found some good stuff. A call to getCachedIntrospectionResults () in the previous code block was wounded by a call to CachedIntrospectionResults # forClass (theClassInQuestion). This returns a CachedIntrospectionResults object that contains far from all expected properties (11 of 21). Going to the forClass method, I found:

 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. 

It turned out that the returned CachedIntrospectionResults were found classCache.get (beanClass). So, what was stored in classCache was damaged / did not contain everything that was supposed to. I set a breakpoint on classCache.get (beanClass) -line and tried to run this through the debugger:

classCache.put (beanClass, null);

When you allow the method to shut down and rebuild CachedIntrospectionResults, everything worked again. So, what is stored in classCache is not in sync with what would and should be created if it was allowed to rebuild it. Whether this is due to something wrong when the first time it is built, or if the Cache class is damaged somewhere along the line that I currently do not know.

I'm starting to suspect that this has something to do with class loaders, as I previously experienced problems due to changes in the way the class loader works when updating Glassfish.

+7
source share
4 answers

I have my colleague investigating the error, and he was able to recreate it in the unit test. This was done by calling a method that creates CachedIntroSpectionResults for the class, while at the same time emphasizing jvm by adding lines to memory with very low memory settings. This approach slowed down 20/30000 times.

In this regard, I received only an oral explanation, so I do not have all the details, but it was something like this: Java has its own introspection results and they are wrapped by Spring, The problem is that the java results use soft links that make them prone to garbage collection. Thus, when Spring created its wrappers around these soft links at the same time that the garbage collector was going to, it actually cleared some of the core of what Spring was using, resulting in a “loss” of properties.

The solution is similar to updating from Spring 3.1.0.RELEASE to Spring 3.1.3.RELEASE. There are some changes here, and Spring no longer wraps soft links when defining class properties (soft link is used in rare, special cases, and not all the time). After updating the Spring version, the error was not reproduced through unit test, it remains to check whether this actually happens in practice.

Update: several weeks have passed, no signs of error. So Spring version upgrade worked :)

+2
source

There may be several reasons. I'm not sure about the reality, but I can give you a way to figure out the problem.

Step 1: on server 2, the machine deploys the application on Glassfish 3.0.1 build 22 , now if it works fine on server 2 the machine, which means that there may be problems with Glass fish libraries, the following may be the cause of this problem

  • Any library that is not in Glassfish 3.1 build 43 that is in Glassfish 3.0.1 build 22 . you can decide by copying all the libraries from the Glassfish production server to the new server.
  • My Glassfish libraries run counter to the spring version. [The Similliar problem I encountered in tomcat, and when I replaced my libraires spring from 3.0.1 to 3.0.3, it worked for me], so replace your spring libraries with the latest.

Step 2: and if the result of step 1 is that the application does not work on server 2 on Glassfish 3.0.1 build 22, there may be the following reason.

  • if any libraries that you inserted into java lib are either not included in this server computer or have different versions.

  • Any folders that are installed in the classpath or using any environment variables on server 1 either do not exist on server 2, or do not have banners or have banks with diff versions

+2
source

I think I actually found a candidate for this.

After receiving an error on one of the test servers after a very short duration and little use, we did some additional verification of the cause. It turned out that the test server had only half the available memory, which made us look at it a little more carefully. It turned out that he had not exhausted all his memory, but using JConsole to study the memory usage in another part of the new generation space on the heap, it turned out that one of the antimony spaces was completely full. I suppose this caused parts of it to overflow, which resulted in the overflow parts being GC-ed or inaccessible, not being where it should have been.

We have yet to verify that this is also a problem in the production environment, but as soon as the error returns, we will check, and if so, we will change some memory parameters to allow more space for the new generation heap survival area. (-XX: SurvivorRatio = 6 or something like that).

Thus, it seems that larger Spring MVC applications need more space for survivors, especially in newer versions of Glassfish.

+1
source

Indeed, there was a problem with the newly introduced ExtendedBeanInfo class in Spring 3.1.0, which was fixed in Spring 3.1.1 - see ( https://jira.spring.io/browse/SPR-8347 ).

0
source

All Articles