Google AppEngine上的FacebookXmlRestClient NotSerializableException

时间:2010-08-30 17:37:44

标签: java google-app-engine facebook facebook-java-api

我试图按照facebook-java-api filter示例进行操作但是我得到了这个期望 我试图将客户端对象保存到会话中。该代码托管在google appengine平台上。

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

    }
}

1 个答案:

答案 0 :(得分:0)

您放入HttpSession的所有对象都需要标记为 Serializable。 (GAE使用数据存储来存储会话数据)

只是想知道,而不是使用HttpSession作为地图中的键,尝试使用会话ID? E.g:

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