2013-08-24 3 views
0

JSF 2.0, Spring Social Facebook 및 Google App Engine을 사용하고 있습니다.NotSerializableException FacebookConnectionFactory

의 web.xml :

<welcome-file-list> 
     <welcome-file>login.jsf</welcome-file> 
    </welcome-file-list> 

login.jsf :

<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:ui="http://java.sun.com/jsf/facelets" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:prime="http://primefaces.org/ui"> 


    <h:outputText value="#{user.text}" /> 

</html> 

UserSessionMbean :

@ManagedBean(name = "user") 
@SessionScoped 
public final class UserSessionMBean implements Serializable { 

OAuth2Operations oauthOperations = null; 
FacebookConnectionFactory connectionFactory = null; 
private Facebook fbUserSession = null; 

private String text = "Loging..."; 

public UserSessionMBean() { 
    connectionFactory = new FacebookConnectionFactory("MY_KEY", 
      "MY_SECRET"); 
    oauthOperations = connectionFactory.getOAuthOperations(); 
} 


public void facebookLogin() { 

    try { 

     ExternalContext ec = FacesContext.getCurrentInstance() 
       .getExternalContext(); 

     HttpServletRequest httpServletRequest = null; 
     Object request = ec.getRequest(); 

     if (request instanceof HttpServletRequest) { 
      httpServletRequest = (HttpServletRequest) request; 
     } 

     String code = httpServletRequest.getParameter("code"); 

     if (StringUtil.isNotBlankStr(code)) { 

      // upon receiving the callback from the provider: 
      AccessGrant accessGrant = oauthOperations.exchangeForAccess(
        code, "http://localhost:8888/", null); 

      Connection<Facebook> connection = connectionFactory 
        .createConnection(accessGrant); 

      setFbUserSession(connection != null ? connection.getApi() 
        : new FacebookTemplate()); 

      ec.getSessionMap().put("fbUserSession", fbUserSession); 

      ec.redirect("init.jsf"); 

     } else { 

      OAuth2Parameters params = new OAuth2Parameters(); 
      params.setRedirectUri("http://localhost:8888/"); 

      params.setScope("publish_stream"); 
      params.setScope("email"); 
      params.setScope("offline_access"); 

      String authorizeUrl = oauthOperations.buildAuthorizeUrl(
        GrantType.AUTHORIZATION_CODE, params); 
      ec.redirect(authorizeUrl); 
      return; 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 


public String getText() { 
    facebookLogin(); 
    return text; 
} 

오류 발생 :

코드를 실행하면 오류를 얻기
ec.getSessionMap().put("fbUserSession", fbUserSession); 

오류 :

23/08/2013 21:36:36 com.google.apphosting.utils.jetty.JettyLogger warn 
AVISO:/
java.lang.RuntimeException: java.io.NotSerializableException:  org.springframework.social.facebook.connect.FacebookConnectionFactory 
     at com.google.appengine.tools.development.SerializableObjectsOnlyHashSessionManager$SerializableObjectsOnlyHttpSession.checkCanSerialize(SerializableObjectsOnlyHashSessionManager.java:66) 
     at com.google.appengine.tools.development.SerializableObjectsOnlyHashSessionManager$SerializableObjectsOnlyHttpSession.setAttribute(SerializableObjectsOnlyHashSessionManager.java:43) 
     at com.sun.faces.context.SessionMap.put(SessionMap.java:141) 
     at com.sun.faces.context.SessionMap.put(SessionMap.java:61) 
     at com.sun.faces.mgbean.BeanManager$ScopeManager$SessionScopeHandler.handle(BeanManager.java:576) 
     at com.sun.faces.mgbean.BeanManager$ScopeManager.pushToScope(BeanManager.java:458) 
     at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:410) 
     at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269) 
     at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244) 
     at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116) 
     at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) 
     at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) 
     at org.apache.el.parser.AstIdentifier.getValue(AstIdentifier.java:68) 
     at org.apache.el.parser.AstValue.getValue(AstValue.java:112) 
     at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186) 
     at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) 
     at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194) 
     at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182) 
     at javax.faces.component.UIOutput.getValue(UIOutput.java:169) 
     at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205) 
     at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:355) 
     at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164) 
     at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) 
     at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) 
     at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) 
     at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:424) 
     at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:124) 
     at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) 
     at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
     at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) 
     at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) 
     at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
     at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:368) 
     at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:351) 
     at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
     at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
     at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
     at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
     at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
     at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:97) 
     at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:327) 
     at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:126) 
     at com.google.appengine.tools.development.StaticFileUtils.serveWelcomeFileAsForward(StaticFileUtils.java:82) 
     at com.google.appengine.tools.development.LocalResourceFileServlet.maybeServeWelcomeFile(LocalResourceFileServlet.java:247) 
     at com.google.appengine.tools.development.LocalResourceFileServlet.doGet(LocalResourceFileServlet.java:120) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
     at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
     at br.com.caronagem.config.HttpIfModifiedSinceFix.doFilter(HttpIfModifiedSinceFix.java:54) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59) 
     at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:368) 
     at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:351) 
     at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116) 
     at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
     at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
     at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
     at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
     at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
     at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
     at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:97) 
     at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
     at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:485) 
     at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
     at org.mortbay.jetty.Server.handle(Server.java:326) 
     at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
     at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923) 
     at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547) 
     at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) 
     at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
     at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) 
     at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 
Caused by: java.io.NotSerializableException: org.springframework.social.facebook.connect.FacebookConnectionFactory 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330) 
     at com.google.appengine.tools.development.SerializableObjectsOnlyHashSessionManager$SerializableObjectsOnlyHttpSession.checkCanSerialize(SerializableObjectsOnlyHashSessionManager.java:64) 
... 89 more 

답변

1

해결책은 간단하다 : 단지 직렬화 클래스의 속성으로 직렬화 인스턴스를 선언하지 않습니다. 세션 범위가 지정된 bean은 하드 디스크 (예 : 메모리 프로필이 낮은 서버) 및/또는 네트워크 (예 : 서버 클러스터)를 통해 전송 될 수 있으므로 직렬화해야합니다. 그러나 "연결"을 나타내는 객체는 분명히 비활성화 될 수 없으므로 직렬화 할 수 없습니다.

세션 범위 Bean을 메소드 로컬 범위에서, 즉 메소드 블록 내에서 완전히 생성 및 파기되도록 다시 작성해야합니다. 메소드를 떠나서는 안됩니다. 적어도 공개 범위에 있지는 않습니다 (개인 정적 헬퍼 메소드는 괜찮습니다).

그래서 그냥 facebookLogin() 방법 내부에 oauthOperations, connectionFactoryfbUserSession의 세 가지 선언을 이동하고 지금까지 외부를 전달하지 않습니다.

public void facebookLogin() { 
    OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations(); 
    FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory("MY_KEY", "MY_SECRET"); 
    Facebook fbUserSession = null; 
    // ... 

또 다른 원인

수동 일부 불분명 한 이유로 HTTP 세션에서 fbUserSession를 배치한다는 것입니다. 너는 그렇게해서는 안된다. fbUserSession 코드가 FB와 상호 작용할 수있는 세션을 나타냅니다. 그러나이 방법을 마친 후에는 열어 둘 수 없습니다. 새 HTTP 요청에 따라 닫히고 다시 열어야합니다. HTTP 세션을 대표하지 않습니다. 대신 FB 세션에서 원하는 정보를 추출한 다음 해당 정보를 세션에 대신 넣어야합니다 (일반적으로 String, Integer 등의 정보를 다른 빈에 랩핑해야 함). 또는 을 현재 세션 범위 지정 Bean의 속성으로 할당하기 만하면됩니다.

+0

이전에는 변수에서 transient를 사용했습니다. 그의 제안에도 같은 결과가있었습니다. 이제이 오류는 java.io.NotSerializableException입니다 : org.springframework.social.connect.support.OAuth2Connection $ ApiInvocationHandler – vctlzac

+0

'transient'를 사용하는 것이 올바른 해결책이 아닙니다. 이러한 변수를 메서드의 로컬 범위에 선언하고 보관하십시오. 그게 다야. – BalusC

+0

나는 그것을했다. 그러나 같은 오류가 발생했습니다. (NotSerializableException : OAuth2Connection $ ApiInvocationHandler) – vctlzac

관련 문제