0

我尝试遵循facebook-java-api 过滤器示例,但是当我尝试将客户端对象保存到会话时,我得到了这个期望。代码托管在 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;
            }

    }
}
4

1 回答 1

0

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

只是想知道,与其使用 HttpSession 作为映射中的键,不如尝试使用会话 ID?例如:

map.put(session.getId(),userClient);
于 2010-09-01T03:11:02.950 回答