You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by Daniel Cunha <da...@gmail.com> on 2014/12/28 12:46:13 UTC

Re: tomee git commit: missing files

Thank you Romain! :)

On Sun, Dec 28, 2014 at 11:43 AM, <rm...@apache.org> wrote:

> Repository: tomee
> Updated Branches:
>   refs/heads/develop 2a9630a02 -> ce3ee00b9
>
>
> missing files
>
>
> Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
> Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/ce3ee00b
> Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/ce3ee00b
> Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/ce3ee00b
>
> Branch: refs/heads/develop
> Commit: ce3ee00b9cafc4cf73ecf57070ab27aa3f611b37
> Parents: 2a9630a
> Author: Romain Manni-Bucau <rm...@apache.org>
> Authored: Sun Dec 28 12:42:36 2014 +0100
> Committer: Romain Manni-Bucau <rm...@apache.org>
> Committed: Sun Dec 28 12:42:36 2014 +0100
>
> ----------------------------------------------------------------------
>  .../openejb/testing/ContainerProperties.java    |  37 +++
>  .../AppComposerClassConfigurationTest.java      |  37 +++
>  ...ghtweightWebAppBuilderListenerExtractor.java |  62 ++++
>  .../server/httpd/OpenEJBAsyncContext.java       | 320 +++++++++++++++++++
>  .../openejb/server/httpd/AsyncHttpTest.java     | 171 ++++++++++
>  5 files changed, 627 insertions(+)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/ce3ee00b/container/openejb-core/src/main/java/org/apache/openejb/testing/ContainerProperties.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/main/java/org/apache/openejb/testing/ContainerProperties.java
> b/container/openejb-core/src/main/java/org/apache/openejb/testing/ContainerProperties.java
> new file mode 100644
> index 0000000..8284bdf
> --- /dev/null
> +++
> b/container/openejb-core/src/main/java/org/apache/openejb/testing/ContainerProperties.java
> @@ -0,0 +1,37 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.openejb.testing;
> +
> +import java.lang.annotation.ElementType;
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.RetentionPolicy;
> +import java.lang.annotation.Target;
> +
> +@Target(ElementType.TYPE)
> +@Retention(RetentionPolicy.RUNTIME)
> +public @interface ContainerProperties {
> +    Property[] value();
> +
> +    @Target(ElementType.PARAMETER) // TODO: method
> +    @Retention(RetentionPolicy.RUNTIME)
> +    public @interface Property {
> +        String IGNORED = "__not__set__so__ignored";
> +
> +        String name();
> +        String value() default IGNORED;
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/ce3ee00b/container/openejb-core/src/test/java/org/apache/openejb/testing/AppComposerClassConfigurationTest.java
> ----------------------------------------------------------------------
> diff --git
> a/container/openejb-core/src/test/java/org/apache/openejb/testing/AppComposerClassConfigurationTest.java
> b/container/openejb-core/src/test/java/org/apache/openejb/testing/AppComposerClassConfigurationTest.java
> new file mode 100644
> index 0000000..f324536
> --- /dev/null
> +++
> b/container/openejb-core/src/test/java/org/apache/openejb/testing/AppComposerClassConfigurationTest.java
> @@ -0,0 +1,37 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.openejb.testing;
> +
> +import org.apache.openejb.junit.ApplicationComposerRule;
> +import org.apache.openejb.loader.SystemInstance;
> +import org.junit.Rule;
> +import org.junit.Test;
> +
> +import static org.junit.Assert.assertEquals;
> +
> +@ContainerProperties(@ContainerProperties.Property(name =
> "AppComposerClassConfigurationTest.test", value = "expected result"))
> +@Classes(context = "app")
> +public class AppComposerClassConfigurationTest {
> +    @Rule
> +    public final ApplicationComposerRule rule = new
> ApplicationComposerRule(this);
> +
> +    @Test
> +    public void run() {
> +        assertEquals("expected result",
> SystemInstance.get().getProperty("AppComposerClassConfigurationTest.test"));
> +        assertEquals("expected result",
> System.getProperty("AppComposerClassConfigurationTest.test"));
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/ce3ee00b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/LightweightWebAppBuilderListenerExtractor.java
> ----------------------------------------------------------------------
> diff --git
> a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/LightweightWebAppBuilderListenerExtractor.java
> b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/LightweightWebAppBuilderListenerExtractor.java
> new file mode 100644
> index 0000000..5dddd47
> --- /dev/null
> +++
> b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/LightweightWebAppBuilderListenerExtractor.java
> @@ -0,0 +1,62 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> +    * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.openejb.server.httpd;
> +
> +import org.apache.openejb.AppContext;
> +import org.apache.openejb.assembler.classic.WebAppBuilder;
> +import org.apache.openejb.core.WebContext;
> +import org.apache.openejb.loader.SystemInstance;
> +import org.apache.openejb.spi.ContainerSystem;
> +import org.apache.openejb.web.LightweightWebAppBuilder;
> +
> +import java.util.ArrayList;
> +import java.util.Collection;
> +import java.util.Collections;
> +
> +// could be optimized since we could bind to the request the listeners in
> org.apache.openejb.server.httpd.OpenEJBHttpRegistry.ClassLoaderHttpListener.onMessage()
> +// but ok for now since that's fully for the embedded mode
> +public final class LightweightWebAppBuilderListenerExtractor {
> +    public static  <T> Collection<T> findByTypeForContext(final String
> context, final Class<T> type) {
> +        final WebAppBuilder builder =
> SystemInstance.get().getComponent(WebAppBuilder.class);
> +        if (!LightweightWebAppBuilder.class.isInstance(builder)) {
> +            return Collections.emptyList();
> +        }
> +
> +        for (final AppContext app :
> SystemInstance.get().getComponent(ContainerSystem.class).getAppContexts()) {
> +            for (final WebContext web : app.getWebContexts()) {
> +                if (web.getContextRoot().replace("/",
> "").equals(context.replace("/", ""))) {
> +                    final Collection<Object> potentials =
> LightweightWebAppBuilder.class.cast(builder).listenersFor(web.getContextRoot());
> +                    if (potentials == null) {
> +                        return Collections.emptyList();
> +                    }
> +                    final Collection<T> filtered = new
> ArrayList<>(potentials.size());
> +                    for (final Object o : potentials) {
> +                        if (type.isInstance(o)) {
> +                            filtered.add(type.cast(o));
> +                        }
> +                    }
> +                    return filtered;
> +                }
> +            }
> +        }
> +        return Collections.emptyList();
> +    }
> +
> +    private LightweightWebAppBuilderListenerExtractor() {
> +        // no-op
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/ce3ee00b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBAsyncContext.java
> ----------------------------------------------------------------------
> diff --git
> a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBAsyncContext.java
> b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBAsyncContext.java
> new file mode 100644
> index 0000000..bdd3b4e
> --- /dev/null
> +++
> b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBAsyncContext.java
> @@ -0,0 +1,320 @@
> +/**
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.openejb.server.httpd;
> +
> +import org.apache.openejb.AppContext;
> +import org.apache.openejb.OpenEJBRuntimeException;
> +import org.apache.openejb.core.WebContext;
> +import org.apache.openejb.loader.SystemInstance;
> +import org.apache.openejb.spi.ContainerSystem;
> +import org.apache.openejb.util.DaemonThreadFactory;
> +
> +import javax.servlet.AsyncContext;
> +import javax.servlet.AsyncEvent;
> +import javax.servlet.AsyncListener;
> +import javax.servlet.ServletContext;
> +import javax.servlet.ServletException;
> +import javax.servlet.ServletRequest;
> +import javax.servlet.ServletResponse;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +import java.io.IOException;
> +import java.net.HttpURLConnection;
> +import java.net.Socket;
> +import java.util.ArrayList;
> +import java.util.List;
> +import java.util.Set;
> +import java.util.concurrent.CopyOnWriteArraySet;
> +import java.util.concurrent.Executors;
> +import java.util.concurrent.ScheduledExecutorService;
> +import java.util.concurrent.TimeUnit;
> +
> +// stupid impl, ~ mock. it handles itself eviction to avoid to have it
> always started which is not the common case
> +public class OpenEJBAsyncContext implements AsyncContext {
> +    private static final Set<OpenEJBAsyncContext> INITIALIZED = new
> CopyOnWriteArraySet<>();
> +    private static volatile ScheduledExecutorService es;
> +
> +    public static void destroy() {
> +        if (es == null) {
> +            return;
> +        }
> +        es.shutdownNow();
> +        for (final OpenEJBAsyncContext ctx : new
> ArrayList<>(INITIALIZED)) {
> +            if (ctx.lastTouch + ctx.getTimeout() <
> System.currentTimeMillis()) {
> +                for (final AsyncListener listener : ctx.listeners) {
> +                    try {
> +                        listener.onTimeout(ctx.event);
> +                    } catch (final IOException t) {
> +                        throw new OpenEJBRuntimeException(t);
> +                    }
> +                }
> +                ctx.complete();
> +            }
> +        }
> +        INITIALIZED.clear();
> +    }
> +
> +    public static void init() {
> +        if
> (!"true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.http.async.eviction",
> "true"))) {
> +            return;
> +        }
> +        es = Executors.newScheduledThreadPool(1, new
> DaemonThreadFactory(OpenEJBAsyncContext.class));
> +        es.scheduleWithFixedDelay(new Runnable() {
> +            @Override
> +            public void run() {
> +                for (final OpenEJBAsyncContext ctx : new
> ArrayList<>(INITIALIZED)) {
> +                    if (ctx.lastTouch + ctx.getTimeout() <
> System.currentTimeMillis()) {
> +                        INITIALIZED.remove(ctx);
> +                        for (final AsyncListener listener :
> ctx.listeners) {
> +                            try {
> +                                listener.onTimeout(ctx.event);
> +                            } catch (final IOException t) {
> +                                throw new OpenEJBRuntimeException(t);
> +                            }
> +                        }
> +                        ctx.complete();
> +                    }
> +                }
> +            }
> +        }, 1, 1, TimeUnit.MINUTES);
> +    }
> +
> +    private final List<AsyncListener> listeners = new ArrayList<>();
> +    private final ServletResponse response;
> +    private final HttpRequestImpl request;
> +    private final Socket socket;
> +    private final AsyncEvent event;
> +    private WebContext context = null;
> +    private volatile boolean started = false;
> +    private volatile boolean committed = false;
> +    private long timeout = 30000;
> +    private long lastTouch = System.currentTimeMillis();
> +
> +    public OpenEJBAsyncContext(final HttpRequestImpl request, final
> ServletResponse response, final String contextPath) {
> +        if (es == null) {
> +            synchronized (OpenEJBAsyncContext.class) { // we don't care
> since impl is not really thread safe, just here for testing
> +                if (es == null) {
> +                    init();
> +                }
> +            }
> +        }
> +
> +        this.request = request;
> +        if (contextPath != null) {
> +            for (final AppContext app :
> SystemInstance.get().getComponent(ContainerSystem.class).getAppContexts()) {
> +                for (final WebContext web : app.getWebContexts()) {
> +                    if (web.getContextRoot().replace("/",
> "").equals(contextPath.replace("/", ""))) {
> +                        this.context = web;
> +                        break;
> +                    }
> +                }
> +            }
> +        }
> +        this.response = response;
> +        this.socket =
> Socket.class.cast(request.getAttribute("openejb_socket"));
> +        this.event = new AsyncEvent(this, request, response);
> +        INITIALIZED.add(this);
> +    }
> +
> +    @Override
> +    public void complete() {
> +        for (final AsyncListener listener : listeners) {
> +            try {
> +                listener.onComplete(event);
> +            } catch (final IOException t) {
> +                throw new OpenEJBRuntimeException(t);
> +            }
> +        }
> +
> +        commit();
> +    }
> +
> +    private void onError(final Throwable ignored) {
> +        for (final AsyncListener listener : listeners) {
> +            try {
> +                listener.onError(event);
> +            } catch (final IOException t) {
> +                throw new OpenEJBRuntimeException(t);
> +            }
> +        }
> +        try {
> +
> HttpServletResponse.class.cast(response).sendError(HttpURLConnection.HTTP_INTERNAL_ERROR);
> +            commit();
> +        } catch (final IOException e) {
> +            // no-op
> +        }
> +    }
> +
> +    private void commit() {
> +        if (committed) { // avoid to commit it twice on errors (often a
> listener will do it, we just force it in case of)
> +            return;
> +        }
> +        committed = true;
> +        if (HttpResponseImpl.class.isInstance(response) && socket !=
> null) {
> +            try {
> +
> HttpResponseImpl.class.cast(response).writeMessage(socket.getOutputStream(),
> false);
> +            } catch (final IOException e) {
> +                // no-op
> +            }
> +        } // else TODO
> +
> +        if (socket != null) {
> +            try {
> +                socket.getInputStream().close();
> +            } catch (final IOException e) {
> +                // no-op
> +            }
> +            try {
> +                socket.getOutputStream().close();
> +            } catch (final IOException e) {
> +                // no-op
> +            }
> +            try {
> +                socket.close();
> +            } catch (final IOException e) {
> +                // no-op
> +            }
> +        }
> +    }
> +
> +    @Override
> +    public void dispatch() {
> +        String path;
> +        final String pathInfo;
> +        ServletRequest servletRequest = getRequest();
> +        if (servletRequest instanceof HttpServletRequest) {
> +            HttpServletRequest sr = (HttpServletRequest) servletRequest;
> +            path = sr.getServletPath();
> +            pathInfo = sr.getPathInfo();
> +        } else {
> +            path = request.getServletPath();
> +            pathInfo = request.getPathInfo();
> +        }
> +        if (pathInfo != null) {
> +            path += pathInfo;
> +        }
> +        dispatch(path);
> +    }
> +
> +    @Override
> +    public void dispatch(final String path) {
> +        dispatch(request.getServletContext(), path);
> +    }
> +
> +    @Override
> +    public void dispatch(final ServletContext context, final String path)
> {
> +        final HttpListenerRegistry registry =
> SystemInstance.get().getComponent(HttpListenerRegistry.class);
> +        try {
> +            final String contextPath =
> this.context.getContextRoot().startsWith("/") ?
> this.context.getContextRoot() : ('/' + this.context.getContextRoot());
> +            final HttpRequestImpl req = new
> HttpRequestImpl(request.getSocketURI()) {
> +                @Override
> +                public String getContextPath() {
> +                    return contextPath;
> +                }
> +
> +                @Override
> +                public String getServletPath() {
> +                    return path;
> +                }
> +
> +                @Override
> +                public String getRequestURI() {
> +                    return contextPath + path;
> +                }
> +            };
> +            registry.onMessage(req,
> HttpResponse.class.isInstance(response) ? HttpResponse.class.cast(response)
> : new ServletResponseAdapter(HttpServletResponse.class.cast(response)));
> +            complete();
> +        } catch (final Exception e) {
> +            onError(e);
> +        }
> +    }
> +
> +    @Override
> +    public ServletRequest getRequest() {
> +        return request;
> +    }
> +
> +    @Override
> +    public ServletResponse getResponse() {
> +        if (response == null) {
> +            throw new IllegalStateException("no response");
> +        }
> +        return response;
> +    }
> +
> +    @Override
> +    public void start(final Runnable run) {
> +        internalStartAsync();
> +        // TODO: another thread
> +        run.run();
> +    }
> +
> +    public void internalStartAsync() {
> +        started = true;
> +        for (final AsyncListener listener : listeners) {
> +            try {
> +                listener.onStartAsync(event);
> +            } catch (final IOException t) {
> +                throw new OpenEJBRuntimeException(t);
> +            }
> +        }
> +    }
> +
> +    @Override
> +    public void addListener(final AsyncListener listener) {
> +        listeners.add(listener);
> +        if (started) {
> +            try {
> +                listener.onStartAsync(event);
> +            } catch (final IOException e) {
> +                throw new OpenEJBRuntimeException(e);
> +            }
> +        }
> +    }
> +
> +    @Override
> +    public void addListener(final AsyncListener listener,
> +                            final ServletRequest servletRequest,
> +                            final ServletResponse servletResponse) {
> +        addListener(listener);
> +    }
> +
> +    @Override
> +    public <T extends AsyncListener> T createListener(final Class<T>
> clazz)
> +            throws ServletException {
> +        try {
> +            return (T) context.inject(clazz.newInstance());
> +        } catch (final Exception e) {
> +            throw new ServletException(e);
> +        }
> +    }
> +
> +    @Override
> +    public boolean hasOriginalRequestAndResponse() {
> +        return true;
> +    }
> +
> +    @Override
> +    public long getTimeout() {
> +        return timeout;
> +    }
> +
> +    @Override
> +    public void setTimeout(long timeout) {
> +        this.timeout = timeout;
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tomee/blob/ce3ee00b/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AsyncHttpTest.java
> ----------------------------------------------------------------------
> diff --git
> a/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AsyncHttpTest.java
> b/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AsyncHttpTest.java
> new file mode 100644
> index 0000000..41c8117
> --- /dev/null
> +++
> b/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AsyncHttpTest.java
> @@ -0,0 +1,171 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> +    * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.openejb.server.httpd;
> +
> +import org.apache.openejb.junit.ApplicationComposerRule;
> +import org.apache.openejb.loader.IO;
> +import org.apache.openejb.testing.Classes;
> +import org.apache.openejb.testing.ContainerProperties;
> +import org.apache.openejb.testing.EnableServices;
> +import org.apache.openejb.testing.RandomPort;
> +import org.junit.Rule;
> +import org.junit.Test;
> +
> +import javax.inject.Inject;
> +import javax.servlet.AsyncContext;
> +import javax.servlet.AsyncEvent;
> +import javax.servlet.AsyncListener;
> +import javax.servlet.ServletException;
> +import javax.servlet.annotation.WebServlet;
> +import javax.servlet.http.HttpServlet;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +import java.io.IOException;
> +import java.net.URL;
> +import java.util.concurrent.ExecutorService;
> +import java.util.concurrent.Executors;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertTrue;
> +
> +@EnableServices("http")
> +@Classes(cdi = true, innerClassesAsBean = true)
> +@ContainerProperties(@ContainerProperties.Property(name =
> "httpejbd.useJetty", value = "fase"))
> +public class AsyncHttpTest {
> +    @Rule
> +    public final ApplicationComposerRule container = new
> ApplicationComposerRule(this);
> +
> +    @RandomPort("http")
> +    private URL context;
> +
> +    @Test
> +    public void async() throws IOException {
> +        SimpleAsyncListener.started = false;
> +        assertEquals("OK", IO.slurp(new URL(context.toExternalForm() +
> "openejb/AsyncServlet")));
> +        assertTrue(SimpleAsyncListener.started);
> +    }
> +
> +    @Test
> +    public void asyncDispatch() throws IOException {
> +        assertEquals("OK2", IO.slurp(new URL(context.toExternalForm() +
> "openejb/DispatchAsyncServlet")));
> +    }
> +
> +    @WebServlet(name = "AsyncServlet", urlPatterns = "/AsyncServlet",
> asyncSupported = true)
> +    public static class AsyncServlet extends HttpServlet {
> +        private ExecutorService executorService;
> +
> +        @Override
> +        public void init() throws ServletException {
> +            executorService = Executors.newSingleThreadExecutor();
> +        }
> +
> +        @Override
> +        protected void service(final HttpServletRequest req, final
> HttpServletResponse resp) throws ServletException, IOException {
> +            final AsyncContext actx = req.startAsync();
> +
> actx.addListener(actx.createListener(SimpleAsyncListener.class));
> +            resp.setContentType("text/plain");
> +            executorService.execute(new AsyncHandler(actx));
> +        }
> +
> +        @Override
> +        public void destroy() {
> +            executorService.shutdownNow();
> +        }
> +    }
> +
> +    @WebServlet(name = "DispatchAsyncServlet", urlPatterns =
> "/DispatchAsyncServlet", asyncSupported = true)
> +    public static class DispatchAsyncServlet extends HttpServlet {
> +        private ExecutorService executorService;
> +
> +        @Override
> +        public void init() throws ServletException {
> +            executorService = Executors.newSingleThreadExecutor();
> +        }
> +
> +        @Override
> +        protected void service(final HttpServletRequest req, final
> HttpServletResponse resp) throws ServletException, IOException {
> +            final AsyncContext actx = req.startAsync();
> +            resp.setContentType("text/plain");
> +            actx.dispatch("/ok");
> +        }
> +
> +        @Override
> +        public void destroy() {
> +            executorService.shutdownNow();
> +        }
> +    }
> +
> +    public static class ABean {}
> +
> +    public static class SimpleAsyncListener implements AsyncListener {
> +        private static boolean started;
> +
> +        @Inject
> +        private ABean bean;
> +
> +        @Override
> +        public void onComplete(final AsyncEvent event) throws IOException
> {
> +            // no-op
> +        }
> +
> +        @Override
> +        public void onTimeout(AsyncEvent event) throws IOException {
> +            // no-op
> +        }
> +
> +        @Override
> +        public void onError(AsyncEvent event) throws IOException {
> +            // no-op
> +        }
> +
> +        @Override
> +        public void onStartAsync(final AsyncEvent event) throws
> IOException {
> +            started = bean != null;
> +        }
> +    }
> +
> +    @WebServlet("/ok")
> +    public static class SimpleServlet extends HttpServlet {
> +        @Override
> +        protected void service(final HttpServletRequest req, final
> HttpServletResponse resp) throws ServletException, IOException {
> +            resp.getWriter().write("OK2");
> +        }
> +    }
> +
> +    private static class AsyncHandler implements Runnable {
> +        private final AsyncContext actx;
> +
> +        public AsyncHandler(final AsyncContext ctx) {
> +            this.actx = ctx;
> +        }
> +
> +        @Override
> +        public void run() {
> +            try {
> +                actx.getResponse().getWriter().write("OK");
> +            } catch (final IOException e) {
> +                try {
> +
> HttpServletResponse.class.cast(actx.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
> +                } catch (final IOException e1) {
> +                    // no-op
> +                }
> +                actx.complete();
> +            }
> +            actx.complete();
> +        }
> +    }
> +}
>
>


-- 
Daniel Cunha (soro)