2010-08-30 281 views
0

我试图按照facebook-java-api filter的例子,但我得到这个期望 我试图保存到会话的客户端对象。该代码托管在谷歌appengine平台上。FacebookXmlRestClient谷歌AppEngine上的NotSerializableException

java.lang.RuntimeException: java.io.NotSerializableException: com.google.code.facebookapi.FacebookXmlRestClient 
    at com.google.apphosting.runtime.jetty.SessionManager.serialize(SessionManager.java:387) 
    at com.google.apphosting.runtime.jetty.SessionManager.createEntityForSession(SessionManager.java:364) 
    at com.google.apphosting.runtime.jetty.SessionManager$AppEngineSession.save(SessionManager.java:164) 
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:41) 
    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 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.net.async.Connection.handleReadEvent(Connection.java:474) 
    at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:831) 
    at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207) 
    at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:103) 
    at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:251) 
    at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:418) 
    at java.lang.Thread.run(Thread.java:636) 
Caused by: java.io.NotSerializableException: com.google.code.facebookapi.FacebookXmlRestClient 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1173) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:343) 
    at java.util.HashMap.writeObject(HashMap.java:1018) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 

我更新了过滤器的代码使用地图保存会话和相关的客户对象,但我仍然可以得到有效的登录。任何人都可以用这段代码发现问题,或者解释如何正确使用com.google.code.facebookapi.ExtensibleClient?

import com.google.code.facebookapi.FacebookException; 
import com.google.code.facebookapi.FacebookWebappHelper; 
import com.google.code.facebookapi.FacebookXmlRestClient; 
import com.google.code.facebookapi.IFacebookRestClient; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.logging.Logger; 

import org.w3c.dom.Document; 

public class FacebookFilter implements Filter { 

     private static final Logger logger = Logger.getLogger(FacebookFilter.class.getName()); 

     private String api_key; 
     private String secret; 
     private static Map map = new HashMap(); 

     public void init(FilterConfig filterConfig) throws ServletException { 
       api_key = filterConfig.getInitParameter("facebook_api_key"); 
       secret = filterConfig.getInitParameter("facebook_secret_key"); 
       if(api_key == null || secret == null) { 
         throw new ServletException("Cannot initialise Facebook User Filter because the " + 
                  "facebook_api_key or facebook_secret context init " + 
                  "params have not been set. Check that they're there " + 
                  "in your servlet context descriptor."); 
       } else { 
         logger.info("Using facebook API key: " + api_key); 
       } 
     } 

     public void destroy() { 
     } 

     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
       try { 
         HttpServletRequest request = (HttpServletRequest)req; 
         HttpServletResponse response = (HttpServletResponse)res; 

         HttpSession session = request.getSession(true); 
         IFacebookRestClient<Document> userClient = getUserClient(session); 
         if(userClient == null) { 
          logger.info("User session doesn't have a Facebook API client setup yet. Creating one and storing it in the user's session."); 
          userClient = new FacebookXmlRestClient(api_key, secret); 
          logger.info("add new session to map "+map.size()+" "+session.getId()+" "+userClient.toString()); 
          map.put(session,userClient); 
         } 

         logger.fine("Creating a FacebookWebappHelper, which copies fb_ request param data into the userClient"); 
         FacebookWebappHelper<Document> facebook = new FacebookWebappHelper<Document>(request, response, api_key, secret, userClient); 
         String nextPage = request.getRequestURI(); 
         nextPage = nextPage.substring(nextPage.indexOf("/", 1) + 1); //cut out the first /, the context path and the 2nd/
         logger.fine(nextPage); 
         boolean redirectOccurred = facebook.requireLogin(nextPage); 
         if(redirectOccurred) { 
           return; 
         } 
         redirectOccurred = facebook.requireFrame(nextPage); 
         if(redirectOccurred) { 
           return; 
         } 

         long facebookUserID; 
         try { 
          facebookUserID = userClient.users_getLoggedInUser(); 
          logger.info("facebookUserID "+facebookUserID+" "+session.getId()); 

         } catch(FacebookException ex) { 
          response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while fetching user's facebook ID"); 
          logger.warning("Error while getting cached (supplied by request params) value " + 
              "of the user's facebook ID or while fetching it from the Facebook service " + 
              "if the cached value was not present for some reason. Cached value = {} "+ userClient.getCacheUserId()); 
          return; 
         } 
         chain.doFilter(request, response); 
       } 
     } 

    public static FacebookXmlRestClient getUserClient(HttpSession session) { 
      if(map.containsKey(session)) 
      { 
       logger.info("return match "+session.getId()); 
       return (FacebookXmlRestClient) map.get(session); 
      }  
      else 
      { 
       logger.warning("getUserClient() null "+session.getId()); 
       return null; 
      } 

    } 
} 

回答

0

,你把在HttpSession任何对象都需要被标记为 Serializable。 (GAE使用数据存储来存储会话数据)

想知道,不是使用HttpSession作为地图中的键,请尝试使用会话ID?例如:

map.put(session.getId(),userClient); 
+0

我没有将userClient设置为http会话或请求对象的属性或参数(以避免可序列化问题),它将被添加到普通映射中。 – emeraldjava 2010-09-01 08:04:36

+0

当你试图将它放在地图中时,是否会出现相同的错误信息?你有没有尝试我的建议(使用会话ID)? – 2010-09-02 03:26:19