Google AppEngine 上的 FacebookXmlRestClient NotSerializedException

发布于 2024-09-16 10:01:57 字数 7495 浏览 5 评论 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;
            }

    }
}

I've tried to follow the facebook-java-api filter example but i got this expection when
i attempted to save to the client object to the session. The code is being hosted on the google appengine platform.

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)

I updated the filter code to use a map to save the session and associated client object but i still can get a valid login. Can anybody spot the issue with this code, or explain how the
com.google.code.facebookapi.ExtensibleClient can be used correctly?

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

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初懵 2024-09-23 10:01:57

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

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

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

Any objects that you put in an HttpSession will need to be marked as
Serializable. (GAE uses the datastore to store session data)

Just wondering, instead of using the HttpSession as the key in the map, try using the session id? E.g.:

map.put(session.getId(),userClient);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文