Question

I'm using JSF 2.0, Spring Social Facebook and Google App Engine. I Getting an error when execute the code:

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

Error occurs in:

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

Error:

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
Était-ce utile?

La solution

The solution is simple: just do not declare non-serializable instances as a property of a serializable class. Session scoped beans needs to be serialize because they can be stored on harddisk (e.g. on a server with low memory profile) and/or transferred over network (e.g. on a server cluster). However, an object which represents a "connection" clearly can't be serialized as such a thing simply can't be passivated.

You need to rewrite your session scoped bean as such that those things are created and destroyed in the method local scope, i.e. entirely inside the method block. It should never leave the method, at least not into the public scope (private static helper methods are okay).

So, just move the three declarations of oauthOperations, connectionFactory and fbUserSession to inside the facebookLogin() method and do not ever pass them outside.

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

Another cause is that you manually placed fbUserSession in the HTTP session for some unclear reason. You should not do that. The fbUserSession represents a session wherein you can let your code interact with FB. But this can't be kept open after the method finishes. It has to be closed and reopened upon a new HTTP request. It does not represent a HTTP session orso. You should instead extract the desired information from FB session and then store that information (usually, in flavor of String, Integer, etc, if necessary wrapped in another bean) in session instead. Or even just assign that as a property of the current session scoped bean.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top