2 Replies Latest reply on Oct 16, 2007 10:47 AM by iradix

    JSF SaveState issues when el-ri.jar is in jsf-libs

    uhyonc

      There seems to be some issues regarding class loaders and the locations of the JSF jars.

      I'm currently using JSF (MyFaces 1.1.4), JBoss4.0.4 and facelets.

      I'm currently using savestate=client, which serializes the component tree. It works very well, except that when I try to register and use JSF functions, I get a ClassNotFoundException AFTER I click a button (that is, after a submit, which deserializes the tree).

      After hours of debugging, I found the problem...

      The problem is that in the el-ri implementation, it retrieves the function's mapped Method in FunctionMapperImpl$Function. The first time around, JSF sets this with the Method using the WebAppClassLoader (probably because it used the Thread context classloader). As the Method m field on FunctionMapperImpl$Function class is transient, after deserialization the code tries to reload the class using Class.forName(className) method, which uses the caller's ClassLoader. That is is uses the el-ri's class loader which, since it's in jsf-libs, is the UnifiedClassLoader. This classloader obviously can't find my custom function class.

      The problem goes away when I use server savestate method with no serialization.

      It would be really nice if JBoss came with a patched el-ri that uses the ThreadClass loader instead of using default Class.forName method. Of course, I'm not sure what other issues that'd cause though... Maybe it can try the default way, and if that doesn't work use the ThreadContextClassLoader

      I hope I saved someone a few hours of debugging... :)

      ---------------- ClassNotFoundException stack -------------
      22:04:10,187 ERROR [STDERR] java.lang.ClassNotFoundException: No ClassLoaders found for: mycompany.Functions
      22:04:10,187 ERROR [STDERR] at org.jboss.mx.loading.LoadMgr3.beginLoadTask(LoadMgr3.java:212)
      22:04:10,187 ERROR [STDERR] at org.jboss.mx.loading.RepositoryClassLoader.loadClassImpl(RepositoryClassLoader.java:511)
      22:04:10,187 ERROR [STDERR] at org.jboss.mx.loading.RepositoryClassLoader.loadClass(RepositoryClassLoader.java:405)
      22:04:10,187 ERROR [STDERR] at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
      22:04:10,187 ERROR [STDERR] at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
      22:04:10,187 ERROR [STDERR] at java.lang.Class.forName0(Native Method)
      22:04:10,187 ERROR [STDERR] at java.lang.Class.forName(Class.java:164)
      22:04:10,187 ERROR [STDERR] at com.sun.el.lang.FunctionMapperImpl$Function.getMethod(FunctionMapperImpl.java:167)
      22:04:10,187 ERROR [STDERR] at com.sun.el.lang.FunctionMapperImpl.resolveFunction(FunctionMapperImpl.java:59)
      22:04:10,187 ERROR [STDERR] at com.sun.el.parser.AstFunction.getValue(AstFunction.java:91)
      22:04:10,187 ERROR [STDERR] at com.sun.el.parser.AstBracketSuffix.getValue(AstBracketSuffix.java:41)
      22:04:10,187 ERROR [STDERR] at com.sun.el.parser.AstValue.getValue(AstValue.java:112)
      22:04:10,187 ERROR [STDERR] at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:192)
      22:04:10,187 ERROR [STDERR] at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
      22:04:10,187 ERROR [STDERR] at com.sun.facelets.el.LegacyValueBinding.getValue(LegacyValueBinding.java:56)
      22:04:10,187 ERROR [STDERR] at javax.faces.component.UIOutput.getValue(UIOutput.java:77)