我正在TomEE中运行一个JSF项目。我将其升级到MyFace 2.1.8。我正在使用Oracle JVM 1.7.04在OSX上运行所有内容
所以我有这个ManagedBean,它是ViewScoped:
@ManagedBean
@ViewScoped
public class BlogMB implements Serializable {
private static final long serialVersionUID = 1L;
@EJB
private CategoryService categoryService;
}
这是视图代码:
<h:commandLink value="#{category.name}">
<f:setPropertyActionListener
target="#{blogMB.selectedCategory}"
value="#{category}" />
<f:ajax
listener="#{blogMB.filterPostsByCategory()}"
execute="@this"
render=":blogPosts" />
</h:commandLink>
此堆栈跟踪中的结果。到底他妈发生了什么?我知道它需要反序列化句柄,但为什么在类路径上找不到我的服务类呢?
Jul 06, 2012 8:25:51 PM org.apache.myfaces.renderkit.ServerSideStateCacheImpl deserializeView
SEVERE: Exiting deserializeView - Could not deserialize state: com.xxx.blog.service.CategoryService
java.lang.ClassNotFoundException: com.xxx.blog.service.CategoryService
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.io.ObjectInputStream.resolveProxyClass(ObjectInputStream.java:694)
at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1549)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1511)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at java.util.HashMap.readObject(HashMap.java:1043)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1004)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1685)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1341)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at java.util.HashMap.readObject(HashMap.java:1043)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1004)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1685)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1341)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at org.apache.myfaces.renderkit.ServerSideStateCacheImpl.deserializeView(ServerSideStateCacheImpl.java:497)
at org.apache.myfaces.renderkit.ServerSideStateCacheImpl.getSerializedViewFromServletSession(ServerSideStateCacheImpl.java:289)
at org.apache.myfaces.renderkit.ServerSideStateCacheImpl.restoreSerializedView(ServerSideStateCacheImpl.java:891)
at org.apache.myfaces.renderkit.html.HtmlResponseStateManager.getState(HtmlResponseStateManager.java:205)
at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.restoreView(DefaultFaceletsStateManagementStrategy.java:207)
at org.apache.myfaces.application.StateManagerImpl.restoreView(StateManagerImpl.java:130)
at org.apache.myfaces.shared.view.ViewDeclarationLanguageBase.restoreView(ViewDeclarationLanguageBase.java:106)
at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.restoreView(FaceletViewDeclarationLanguage.java:2109)
at org.apache.myfaces.application.ViewHandlerImpl.restoreView(ViewHandlerImpl.java:300)
at com.ocpsoft.pretty.faces.application.PrettyViewHandler.restoreView(PrettyViewHandler.java:109)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:83)
at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:127)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.omnifaces.filter.GzipResponseFilter.doFilter(GzipResponseFilter.java:147)
at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:75)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
编辑更新:
答案 0 :(得分:3)
看起来我们需要在MyFaces中修补deserializeView
方法。长话短说明ObjectInputStream不使用Thread上下文ClassLoader(Thread.currentThread().getClassLoader()
)。所以这种“使用正确的类加载器,该死的!”修复在app服务器中非常普遍。如果MyFaces在WEB-INF/lib/
中,那么这将会神奇地消失,因为MyFaces和被反序列化的类将在同一个类加载器中。但是,移动MyFaces不是正确的解决方案。修补它更好。
当进行反序列化的类在父类加载器中,因此无法从众多子类加载器中看到类(每个webapp一个)时,通常必须这样做:
import java.io.*;
import java.lang.reflect.Proxy;
public class SmarterObjectInputStream extends ObjectInputStream {
public SmarterObjectInputStream(InputStream in) throws IOException {
super(in);
}
protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
try {
return Class.forName(classDesc.getName(), false, getClassloader());
} catch (ClassNotFoundException e) {
String n = classDesc.getName();
if (n.equals("boolean")) return boolean.class;
if (n.equals("byte")) return byte.class;
if (n.equals("char")) return char.class;
if (n.equals("short")) return short.class;
if (n.equals("int")) return int.class;
if (n.equals("long")) return long.class;
if (n.equals("float")) return float.class;
if (n.equals("double")) return double.class;
throw e;
}
}
protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
Class[] cinterfaces = new Class[interfaces.length];
for (int i = 0; i < interfaces.length; i++)
cinterfaces[i] = getClassloader().loadClass(interfaces[i]);
try {
return Proxy.getProxyClass(getClassloader(), cinterfaces);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
private ClassLoader getClassloader() {
return Thread.currentThread().getContextClassLoader();
}
}
我们需要为此SmarterObjectInputStream
提供MyFaces,并确保他们在deserializeView
方法中使用它。
如果您希望获得修补的荣誉,那就太棒了,我确信MyFaces非常热衷于看到TomEE用户提供修复。到目前为止,你已经做了很多贡献!
答案 1 :(得分:0)
可以在web.xml中设置以下可能的解决方法:
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
这是相当不标准的,但我没有对此进行过测试。