Details

    • Type: New Feature New Feature
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.0-Alpha3
    • Fix Version/s: None
    • Component/s: Push Library
    • Labels:
      None
    • Environment:
      ICEpush, Google App Engine

      Description

      It would be useful to support ICEpush on Google App Engine.

        Activity

        Hide
        Ted Goddard added a comment - - edited

        Supporting ICEpush on GAE is fundamentally difficult and may require changes to GAE. consider the following Servlet. The expected behavior is that an initial request to the URL should block and then be unblocked by the next request. Each successive request should unblock the previous one.

        package org.icepush;

        import javax.servlet.ServletException;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import javax.servlet.ServletConfig;
        import javax.servlet.Servlet;
        import javax.servlet.ServletContext;
        import javax.servlet.http.HttpServlet;
        import java.io.IOException;
        import java.io.Writer;

        import java.util.Collections;
        import net.sf.jsr107cache.Cache;
        import net.sf.jsr107cache.CacheException;
        import net.sf.jsr107cache.CacheFactory;
        import net.sf.jsr107cache.CacheManager;
        import net.sf.jsr107cache.CacheListener;

        public class BlockingServlet extends HttpServlet implements CacheListener {
        private ServletContext context;
        private Object kicker = new Object();
        private static Cache cache;
        private static String CACHE_KICK = "cachekick";

        public void init(ServletConfig servletConfig) throws ServletException

        { super.init(servletConfig); context = servletConfig.getServletContext(); initCache(); }

        public void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException {
        Writer out = servletResponse.getWriter();
        cache.put(CACHE_KICK, CACHE_KICK);
        long startMillis = System.currentTimeMillis();
        synchronized (kicker) {
        kicker.notifyAll();
        try

        { kicker.wait(10000); }

        catch (Exception e)

        { out.write(e.toString()); }

        }
        out.write("hello, you waited " + (System.currentTimeMillis() - startMillis) + " on " +kicker +"\n");
        }

        public void initCache() {

        try {
        if (null == cache)

        { System.out.println("initializing memcache"); cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap()); }

        } catch (CacheException e)

        { System.out.println(e); }

        cache.addListener(this);
        }

        public void onLoad(Object key)

        { System.out.println("cache onLoad " + key); }

        public void onPut(Object key){
        System.out.println("should be kicking from cache onPut " + key);
        // synchronized (kicker)

        { // kicker.notifyAll(); // }

        }

        public void onEvict(Object key)

        { System.out.println("cache onEvict " + key); }

        public void onRemove(Object key)

        { System.out.println("cache onRemove " + key); }

        public void onClear()

        { System.out.println("cache clear"); }

        }

        Show
        Ted Goddard added a comment - - edited Supporting ICEpush on GAE is fundamentally difficult and may require changes to GAE. consider the following Servlet. The expected behavior is that an initial request to the URL should block and then be unblocked by the next request. Each successive request should unblock the previous one. package org.icepush; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletConfig; import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; import java.io.IOException; import java.io.Writer; import java.util.Collections; import net.sf.jsr107cache.Cache; import net.sf.jsr107cache.CacheException; import net.sf.jsr107cache.CacheFactory; import net.sf.jsr107cache.CacheManager; import net.sf.jsr107cache.CacheListener; public class BlockingServlet extends HttpServlet implements CacheListener { private ServletContext context; private Object kicker = new Object(); private static Cache cache; private static String CACHE_KICK = "cachekick"; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); context = servletConfig.getServletContext(); initCache(); } public void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException { Writer out = servletResponse.getWriter(); cache.put(CACHE_KICK, CACHE_KICK); long startMillis = System.currentTimeMillis(); synchronized (kicker) { kicker.notifyAll(); try { kicker.wait(10000); } catch (Exception e) { out.write(e.toString()); } } out.write("hello, you waited " + (System.currentTimeMillis() - startMillis) + " on " +kicker +"\n"); } public void initCache() { try { if (null == cache) { System.out.println("initializing memcache"); cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap()); } } catch (CacheException e) { System.out.println(e); } cache.addListener(this); } public void onLoad(Object key) { System.out.println("cache onLoad " + key); } public void onPut(Object key){ System.out.println("should be kicking from cache onPut " + key); // synchronized (kicker) { // kicker.notifyAll(); // } } public void onEvict(Object key) { System.out.println("cache onEvict " + key); } public void onRemove(Object key) { System.out.println("cache onRemove " + key); } public void onClear() { System.out.println("cache clear"); } }
        Hide
        Ted Goddard added a comment -

        Although the above Servlet runs well on the GAE simulator, it does not provide push capability on the GAE cloud. A possible explanation is as follows:

        When a request is blocked, GAE chooses to send successive requests to newly spawned virtual machines. These new virtual machines have different Servlet contexts and do not have access to the same Object being used in the wait/notify. Less defensible is that when the memcache listener API is used, the onPut() callback is not delivered across virtual machines (although this has been verified to work well in the GAE simulator).

        Show
        Ted Goddard added a comment - Although the above Servlet runs well on the GAE simulator, it does not provide push capability on the GAE cloud. A possible explanation is as follows: When a request is blocked, GAE chooses to send successive requests to newly spawned virtual machines. These new virtual machines have different Servlet contexts and do not have access to the same Object being used in the wait/notify. Less defensible is that when the memcache listener API is used, the onPut() callback is not delivered across virtual machines (although this has been verified to work well in the GAE simulator).

          People

          • Assignee:
            Ted Goddard
            Reporter:
            Ted Goddard
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: