W mojej aplikacji serwerowej Java Google App Engine chciałbym włączyć serwlety Channel Presence w celu śledzenia połączeń/rozłączeń z moimi kanałami za pomocą interfejsu Channel API (zgodnie z opisem tutaj. Już edytowałem mój plik WEB-INF/appengine-web.xml zgodnie z opisem.

Większość serwletów w mojej aplikacji używa Sitebricks zamiast klas rozszerzających HttpServlet, aby zapewnić mi łatwy sposób tworzenia punktów końcowych REST w mojej aplikacji. ALE wygląda na to, że używanie Sitebricks w mojej klasie nie działa, ponieważ otrzymuję WARNING: No file found for: /_ah/channel/connected/ po trafieniu w adres URL:

@At("/_ah/channel")
@Service
public class MyChannelPresenceServlet {
    ...
    @Post("/connected")
    public void connectedMethod() {
        ...
    }

    @Post("/disconnected")
    public void disconnectedMethod() {
        ...
    }
    ...
}

Czy jest jakiś sposób na użycie Sitebricks w celu dostarczenia punktu końcowego adresu URL REST dla obecności na kanale, dla /-ah/channel/connected/ i /_ah/channel/disconnected/?

PYTANIE BONUSOWE

Powiedzmy, że Sitebricks nie jest właściwą drogą i zamiast tego muszę trzymać się normalnych klas serwletów, które extends HttpServlet są konfigurowane przez WEB-INF/web.xml. To inne rozwiązanie nadal nie działa dla mnie. Powiedzmy, że mam to wstawić do mojego pliku web.xml:

<servlet>
    <servlet-name>channel_connect</servlet-name>
    <servlet-class>com.example.PresenceServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>channel_connect</servlet-name>
    <url-pattern>/_ah/channel/connected/</url-pattern>
</servlet-mapping>

W tym przykładzie com.example.PresenceServlet jest elementem podrzędnym HttpServlet i zastępuje metodę doPost(HttpServletRequest, HttpServletResponse) z elementu nadrzędnego. NADAL napotykam problemy:

WARNING: /_ah/channel/connected/
java.lang.InstantiationException: com.ea.pogosocial.rest.ChannelServiceServlet
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:325)
at org.mortbay.jetty.servlet.Holder.newInstance(Holder.java:153)
at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:428)
at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:66)
at com.google.sitebricks.SitebricksFilter.doFilter(SitebricksFilter.java:88)
at com.google.inject.servlet.FilterDefinition.doFilter(FilterDefinition.java:163)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:58)
at com.google.sitebricks.HiddenMethodFilter.doFilter(HiddenMethodFilter.java:75)
at com.google.inject.servlet.FilterDefinition.doFilter(FilterDefinition.java:163)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:58)
at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59)
at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49)
at com.google.inject.servlet.FilterDefinition.doFilter(FilterDefinition.java:163)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:58)
at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118)
at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.appstats.AppstatsFilter.doFilter(AppstatsFilter.java:141)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:110)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61)
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 com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
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.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:380)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Cała pomoc jest bardzo ceniona. Zwłaszcza od pracownika Google.

(PS: używam GAE SDK 1.7.2. Z niecierpliwością czekam na wydanie 1.7.3)


Aktualizacja

Był jeszcze jeden eksperyment, którego próbowałem. W znaczniku <servlet> pliku web.xml dla mojej klasy serwletów dodałem ten znacznik, aby wymusić ładowanie mojego serwletu przy starcie serwera (co, nawiasem mówiąc, odbywa się za pomocą mvn gae:run w moim przykład). Teraz mam to wyjście

WARNING: /_ah/channel/connected/: javax.servlet.UnavailableException: java.lang.InstantiationException: com.ea.pogosocial.rest.ChannelServiceServlet
0
ecbrodie 17 październik 2012, 02:04

2 odpowiedzi

Najlepsza odpowiedź

Hmm, szkoda. Wygląda na to, że GAE dokonuje introspekcji łańcucha serwletów w celu znalezienia zarejestrowanego programu obsługi /_ah/kanał/*

Zastrzeżenie: Jestem twórcą zarówno Sitebricks, jak i Guice Servlet, więc uważam to za dość frustrujące. Kiedy raz zaimplementowałem konfigurację kanału w GAE, udało mi się to zrobić bezpośrednio za pomocą Channel API: https://github .com/dhanji/crosstalk/blob/master/src/main/java/com/wideplay/crosstalk/web/RoomPage.java

3
Dhanji R. Prasanna 23 październik 2012, 06:16

Jeśli kogoś to jeszcze obchodzi...

Problem polegał na tym, że nie mogłem użyć ani Sitebricks ani Wstrzykiwania wskazówek dla serwletu, który obsługuje żądania POST do identyfikatorów URI usługi Channel Presence. Gdy usunąłem oba, aplet zadziałał jak czar.

0
ecbrodie 22 październik 2012, 16:10