Java JSF2.0@EJB注入@ViewScoped导致MyFaces成为CFNE
我在TomEE中运行一个JSF项目。我把它升级到MyFace 2.1.8。我使用Oracle JVM 1.7.04在OSX上运行一切 因此,我有一个可视范围的ManagedBean:Java JSF2.0@EJB注入@ViewScoped导致MyFaces成为CFNE,java,jsf-2,java-ee-6,myfaces,apache-tomee,Java,Jsf 2,Java Ee 6,Myfaces,Apache Tomee,我在TomEE中运行一个JSF项目。我把它升级到MyFace 2.1.8。我使用Oracle JVM 1.7.04在OSX上运行一切 因此,我有一个可视范围的ManagedBean: @ManagedBean @ViewScoped public class BlogMB implements Serializable { private static final long serialVersionUID = 1L; @EJB private CategoryServi
@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>
编辑更新:
记录的票证看起来我们需要修补MyFaces中的
反序列化视图
方法。长话短说ObjectInputStream不使用线程上下文类加载器(Thread.currentThread().getClassLoader()
)。所以这种“使用正确的类加载器,该死!”的修复在应用服务器中非常普遍。如果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();
}
}
import java.io.*;
导入java.lang.reflect.Proxy;
公共类SmarterObjectInputStream扩展了ObjectInputStream{
公共SmarterObjectInputStream(InputStream in)引发IOException{
超级(in),;
}
受保护类resolveClass(ObjectStreamClass classDesc)引发IOException、ClassNotFoundException{
试一试{
返回Class.forName(classDesc.getName(),false,getClassloader());
}catch(classnotfounde异常){
字符串n=classDesc.getName();
if(n.equals(“boolean”))返回boolean.class;
if(n.equals(“byte”))返回byte.class;
if(n.equals(“char”))返回char.class;
如果(n.equals(“short”))返回short.class;
如果(n.equals(“int”))返回int.class;
如果(n.equals(“long”))返回long.class;
如果(n.equals(“float”))返回float.class;
如果(n.equals(“double”))返回double.class;
投掷e;
}
}
受保护的类resolveProxyClass(字符串[]接口)引发IOException、ClassNotFoundException{
Class[]cinterfaces=新类[interfaces.length];
for(int i=0;i
我们需要给MyFaces这个SmarterObjectInputStream
,并确保他们在deserializeView
方法中使用它
如果你想获得做补丁的荣誉,那就太棒了,我相信MyFaces会非常热衷于看到TomEE用户贡献补丁。到目前为止,你已经做出了很大的贡献 可以在web.xml中设置以下可能的解决方法:
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
org.apache.myfaces.SERIALIZE_STATE_IN_SESSION
假的
这是相当非标准的,我还没有测试过。那么如果不是当前线程的,它使用的是哪个类加载器呢?我从来没有真正见过contextClassLoader(eeek),我将不得不去填补我知识中的这个漏洞。我发现了这个:不错的解释。这是另一个层次结构,但根是加载应用程序的线程,而不是JVM的根类加载器。可能是为什么我从来没有听说过!!
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>