NotSerializableException FacebookConnectionFactory

时间:2013-08-24 00:56:35

标签: google-app-engine jsf-2 jetty spring-social-facebook

我正在使用JSF 2.0,Spring Social Facebook和Google App Engine。我在执行代码时遇到错误:

的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 个答案:

答案 0 :(得分:1)

解决方案很简单:只是不要将非可序列化实例声明为可序列化类的属性。会话范围的bean需要序列化,因为它们可以存储在硬盘上(例如,在具有低内存配置文件的服务器上)和/或通过网络传输(例如,在服务器集群上)。但是,一个代表“连接”的对象显然不能被序列化,因为这样的东西根本无法被钝化。

您需要重写会话范围bean,以便在方法本地范围内创建和销毁这些内容,即完全在方法块内。它永远不应该离开方法,至少不要进入公共范围(私有静态助手方法是可以的)。

因此,只需将oauthOperationsconnectionFactoryfbUserSession的三个声明移到facebookLogin()方法内,不要将它们传递到外面。

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

另一个原因是您出于某些不明原因手动将fbUserSession放入HTTP会话中。你不应该这样做。 fbUserSession代表一个会话,其中可以让您的代码与FB交互。但是在方法完成后,这不能保持打开状态。它必须在新的HTTP请求时关闭并重新打开。它不代表HTTP会话orso。您应该从FB会话中提取所需的信息,然后在会话中存储该信息(通常,以StringInteger等的风格,如果必要,包含在另一个bean中)。或者甚至只将 指定为当前会话作用域bean的属性。