Зарегистрируйте ServletContainer программно в Osgi

Я разрабатываю приложение JAX-RS с OSGI, где ресурсы загружаются динамически. Для этого мне нужно зарегистрировать ServletContainer программно, после чего я могу вызвать метод ServletContainer.reload(ResourceConfig). Я работаю в среде OSGI с поддержкой сервлета 3.x, используя PAX-WEB 3.0.2 и Jersey 2.4. Проблема в том, что когда я хочу получить доступ к ресурсу, который реализует событие, отправленное сервером, Джерси выдает ошибку, которая не поддерживает асинхронность, потому что он работает в сервлете 2.x.

Здесь исключение:

2013-11-05 00:22:37,675 | WARN  | qtp27902282-62   | ServletHandler                   | pse.jetty.servlet.ServletHandler  492 | 60 - org.eclipse.jetty.aggregate.jetty-all-server - 8.1.9.v20130131 |
javax.servlet.ServletException: java.lang.UnsupportedOperationException: Asynchronous processing not supported on Servlet 2.x container.
        at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1448)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.ops4j.pax.web.service.internal.WelcomeFilesFilter.doFilter(WelcomeFilesFilter.java:185)[70:org.ops4j.pax.web.pax-web-runtime:3.0.2]
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1419)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:455)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:69)[71:org.ops4j.pax.web.pax-web-jetty:3.0.2]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:210)[71:org.ops4j.pax.web.pax-web-jetty:3.0.2]
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:77)[71:org.ops4j.pax.web.pax-web-jetty:3.0.2]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.Server.handle(Server.java:368)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:488)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:932)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:994)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:640)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)[60:org.eclipse.jetty.aggregate.jetty-all-server:8.1.9.v20130131]
        at java.lang.Thread.run(Thread.java:724)[:1.7.0_40]
Caused by: java.lang.UnsupportedOperationException: Asynchronous processing not supported on Servlet 2.x container.
        at org.glassfish.jersey.servlet.WebComponent$1.suspend(WebComponent.java:120)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]
        at org.glassfish.jersey.servlet.internal.ResponseWriter.suspend(ResponseWriter.java:109)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]
        at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:621)[219:org.glassfish.jersey.core.jersey-server:2.3.1]
        at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:357)[219:org.glassfish.jersey.core.jersey-server:2.3.1]
        at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:347)[219:org.glassfish.jersey.core.jersey-server:2.3.1]
        at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:258)[219:org.glassfish.jersey.core.jersey-server:2.3.1]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)[220:org.glassfish.jersey.core.jersey-common:2.3.1]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)[220:org.glassfish.jersey.core.jersey-common:2.3.1]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315)[220:org.glassfish.jersey.core.jersey-common:2.3.1]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297)[220:org.glassfish.jersey.core.jersey-common:2.3.1]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:267)[220:org.glassfish.jersey.core.jersey-common:2.3.1]
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)[220:org.glassfish.jersey.core.jersey-common:2.3.1]
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)[219:org.glassfish.jersey.core.jersey-server:2.3.1]
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:983)[219:org.glassfish.jersey.core.jersey-server:2.3.1]
        at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:359)[224:org.glassfish.jersey.containers.jersey-container-servlet-core:2.3.1]

Я пытался зарегистрировать ServletContainer различными способами, но ни один из них не работает, и я думаю, что проблема заключается в регистрации и настройках Джерси, потому что я записал асинхронный сервлет на основе событий, отправленных сервером, и все прошло отлично.

Пример кода:

        ServletContainer container = new ServletContainer();
        ...
        ...
        webContainerRef = bc.getServiceReference(WebContainer.class);
        started = webContainerRef != null;
        if (started) {
            final WebContainer webContainer = (WebContainer) bc
                    .getService(webContainerRef);
            if (webContainer != null) {
                // create a default context to share between registrations
                final HttpContext httpContext = webContainer
                        .createDefaultHttpContext();
                // set a session timeout of 10 minutes
                webContainer.setSessionTimeout(10, httpContext);
                // register the hello world servlet for filtering with url
                // pattern
                final Dictionary<String, Object> initParamsServlet = new Hashtable<String, Object>();
                initParamsServlet.put("javax.ws.rs.Application", "com.workingflows.osgi.jaxrs.samples.conf.MyJaxApp");
                webContainer.registerServlet(
                        container, // registered
                        new String[]{"/rest/*"}, // url patterns
                        initParamsServlet, // init params
                        1,
                        true,
                        httpContext // http context
                );

                webContainer.registerServlet(
                        (HttpServlet) new SseServlet(), // registered
                        new String[]{"/servlet/sse"}, // url patterns
                        initParamsServlet, // init params
                        1,
                        true,
                        httpContext // http context
                );
            }
      }
     ...
     ...

Вот мой репозиторий кода. См. проект OsgiJersey.


person Cristian Rinaldi    schedule 06.11.2013    source источник


Ответы (2)


У вас есть модуль jersey-container-servlet в пути к классам (это модуль, который предполагается использовать для поддержки Servlet 3.x)?

Причина, по которой вы столкнулись с этой проблемой, заключается в том, что Джерси не удалось найти соответствующий AsyncContextDelegateProvider (из модуля jersey-container-servlet) и использует реализацию из модуля jersey-container-servlet-core (поддержка Servlet 2.x), которая не работает таким образом.

person Michal Gajdos    schedule 06.11.2013
comment
Да, но сервлет-контейнер-джерси находится в пути к классам. - person Cristian Rinaldi; 06.11.2013

Ошибка заключалась в том, что трикотажные модули инициировались на том же уровне, что и модуль приложения, зарегистрировавшего servletContainer.

[ 127] [  Resolved] [   30] jersey-container-servlet-core (2.4.0)
[ 161] [    Active] [   30] jersey-core-common (2.4.0)
[ 162] [    Active] [   30] jersey-core-client (2.4.0)
[ 163] [    Active] [   30] jersey-core-server (2.4.0)
[ 164] [    Active] [   30] jersey-container-servlet (2.4.0)
[ 165] [    Active] [   30] jersey-media-sse (2.4.0)

Запускаю стек майки на 30 уровне, а приложение на 80 уровне и все работает!!!! Важным модулем является jersey-core-server, который добавляет поддержку сервлета 3.x.

[ 168] [    Active] [   80] OsgiJersey OSGi Bundle (1.0.0.SNAPSHOT)

См. пример в моем репозитории.

person Cristian Rinaldi    schedule 06.11.2013