我正在使用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
答案 0 :(得分:1)
解决方案很简单:只是不要将非可序列化实例声明为可序列化类的属性。会话范围的bean需要序列化,因为它们可以存储在硬盘上(例如,在具有低内存配置文件的服务器上)和/或通过网络传输(例如,在服务器集群上)。但是,一个代表“连接”的对象显然不能被序列化,因为这样的东西根本无法被钝化。
您需要重写会话范围bean,以便在方法本地范围内创建和销毁这些内容,即完全在方法块内。它永远不应该离开方法,至少不要进入公共范围(私有静态助手方法是可以的)。
因此,只需将oauthOperations
,connectionFactory
和fbUserSession
的三个声明移到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会话中提取所需的信息,然后在会话中存储该信息(通常,以String
,Integer
等的风格,如果必要,包含在另一个bean中)。或者甚至只将 指定为当前会话作用域bean的属性。