2012-07-07 3 views
2

TomEE에서 JSF 프로젝트를 실행하고 있습니다. 나는 그것을 MyFace 2.1.8로 업그레이드했다. 나는 오라클 JVM으로 OSX에 모든 것을 실행하는거야 1.7.04JSF2.0 @EJB @ViewScoped에 삽입하여 MyFaces를 CFNE로 만듭니다

그래서 ViewScoped 인이 ManagedBean은이 :이 스택 트레이스에서

<h:commandLink value="#{category.name}"> 
    <f:setPropertyActionListener 
     target="#{blogMB.selectedCategory}" 
     value="#{category}" /> 
    <f:ajax 
     listener="#{blogMB.filterPostsByCategory()}" 
     execute="@this" 
     render=":blogPosts" /> 
</h:commandLink> 

결과 : 여기

@ManagedBean 
@ViewScoped 
public class BlogMB implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @EJB 
    private CategoryService categoryService; 
} 

뷰 코드입니다 . 도대체 무슨 일이야? 핸들을 deserialize 할 필요가 있다는 것을 알고 있지만 classpath에서 내 서비스 클래스를 찾는 데 왜 문제가 있습니까?

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) 

편집 업데이트 : 우리가에서 MyFaces에 deserializeView 방법을 패치해야처럼

기록 된 티켓 https://issues.apache.org/jira/browse/MYFACES-3581

답변

3

보인다. 길게 이야기가 짧으면 ObjectInputStream은 Thread 컨텍스트 ClassLoader (Thread.currentThread().getClassLoader())를 사용하지 않습니다. 그래서 이런 종류의 "올바른 클래스 로더를 사용하십시오. 젠장!" 응용 프로그램 서버에서 수정이 매우 보편적입니다. MyFaces가 WEB-INF/lib/에 있으면 MyFaces와 deserialize 될 클래스가 같은 클래스 로더에 있기 때문에 이것은 마술처럼 사라질 것입니다. 그러나 MyFaces를 이동하는 것은 올바른 해결책이 아닙니다. 패치를하는 것이 좋습니다. 직렬화 복원을하는 클래스가 다수의 하위 클래스 로더 (각 웹 애플리케이션에 대해 하나)에서 수업을 볼 수 없습니다, 따라서 부모 클래스 로더에 있고 때

, 당신은 일반적으로이 작업을 수행해야한다 :

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

우리는해야합니다 MyFaces에게 SmarterObjectInputStream을주고 deserializeView 메소드에서 사용하는지 확인하십시오.

패치 적용의 영예를 원한다면, 환상적 일 수 있습니다. MyFaces가 TomEE 사용자가 수정 사항을 제공하는 것을 매우 열정적으로 보게 될 것이라고 확신합니다. 지금까지 큰 공헌을했습니다!

+0

그래서 어떤 클래스 로더가 현재 스레드의? contextClassLoader (eeek)를 본적이 없습니다. 내 지식으로이 구멍을 채우십시오. –

+0

ok 이것을 찾았습니다. http://docs.oracle.com/javase/jndi/tutorial/beyond/misc/classloader .html 괜찮은 설명. 또 다른 계층 구조이지만 루트는 JVM의 루트 클래스 로더가 아닌 응용 프로그램을로드 한 스레드입니다. 아마 내가 그것에 대해 들어 본 적이없는 이유! –

0

가능한 해결 방법은 당신의 web.xml에 다음을 설정할 수 있습니다 :

<context-param> 
    <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name> 
    <param-value>false</param-value> 
</context-param> 

이 그래도 꽤 표준이 아닌 내가이 테스트하지 않았습니다.