Search code examples
javaasynchronousjersey

AsyncResponse throws Exception if not completed within method life time


I just tried out the example of the Jersey tutorial which concerns AsyncResponse and can be found here: http://jersey.java.net/apidocs/snapshot/jersey/javax/ws/rs/container/AsyncResponse.html

It does not seem to work. Even the example throws an exception when executed in a simple unit test:

public class AsyncTest extends JerseyTest {

    @Override
    protected Application configure() {
        return new ResourceConfig(MyAsync.class)
    }

    @Path("/async")
    public static class MyAsync {
        @GET
        public void asyncGet(@Suspended final AsyncResponse asyncResponse) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                    String result = veryExpensiveOperation();
                    asyncResponse.resume(result);
                }

                private String veryExpensiveOperation() {
                    return "bla";
                }
            }).start();
        }
    }

    @Test
    public void testConvertWordToPdf() throws Exception {
        String result = target().path("async").request().async().get().get(String.class);
    }
}

Can somebody tell me what I am doing wrong? Thanks for any answer!

Update: I even tried the official example that can be found at http://search.maven.org/#artifactdetails|org.glassfish.jersey.examples|server-async-standalone-webapp|2.1|war and I get the same exception. The example works, if I make sure the AsyncResponse responds before the method returns. The stack trace I get:

java.util.concurrent.ExecutionException: javax.ws.rs.ProcessingException: java.lang.NullPointerException at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:306) at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:293) at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116) at MyCompany.jersey.ConverterResourceTest.testTest(MyClass.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84) at org.testng.internal.Invoker.invokeMethod(Invoker.java:714) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111) at org.testng.TestRunner.privateRun(TestRunner.java:767) at org.testng.TestRunner.run(TestRunner.java:617) at org.testng.SuiteRunner.runTest(SuiteRunner.java:334) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291) at org.testng.SuiteRunner.run(SuiteRunner.java:240) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224) at org.testng.TestNG.runSuitesLocally(TestNG.java:1149) at org.testng.TestNG.run(TestNG.java:1057) at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175) at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:111) Caused by: javax.ws.rs.ProcessingException: java.lang.NullPointerException at org.glassfish.jersey.client.ClientRuntime$1$1.failure(ClientRuntime.java:148) at org.glassfish.jersey.test.inmemory.internal.InMemoryConnector$3.run(InMemoryConnector.java:265) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:293) at com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:49) at org.glassfish.jersey.test.inmemory.internal.InMemoryConnector.apply(InMemoryConnector.java:257) at org.glassfish.jersey.client.ClientRuntime$1.run(ClientRuntime.java:156) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:267) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:322) at org.glassfish.jersey.client.ClientRuntime$2.run(ClientRuntime.java:170) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) at java.lang.Thread.run(Thread.java:662) Caused by: java.lang.NullPointerException at org.glassfish.jersey.internal.util.KeyComparatorHashMap.putAll(KeyComparatorHashMap.java:509) at javax.ws.rs.core.AbstractMultivaluedMap.putAll(AbstractMultivaluedMap.java:332) at org.glassfish.jersey.test.inmemory.internal.InMemoryConnector.createClientResponse(InMemoryConnector.java:286) at org.glassfish.jersey.test.inmemory.internal.InMemoryConnector.apply(InMemoryConnector.java:247) at org.glassfish.jersey.test.inmemory.internal.InMemoryConnector$3.run(InMemoryConnector.java:261) ... 20 more


Solution

  • Btw, I tested this testcase in Grizzly container. It is not supported in InMemory container as the container does not implement suspend operation on the ContainerResponseWriter. InMemoryResponseWriter should throw an UnsupportedOperationException instead of returning false. This sounds like a Jersey bug.

    @Test
    public void testConvertWordToPdf() throws Exception {
        String result = target().path("async").request().async().get().get().readEntity(String.class);
        assertEquals("bla", result);
    }
    

    Here is my POM dependency:

        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
            <version>2.1</version>
            <scope>test</scope>
        </dependency>