0

I have implemented various Spring MVC REST endpoints to expose services that return a DeferredResult which is handed off to an Akka TypedActor to be completed. The application is deployed into a Glassfish 4 server.

Generally the services execute and return as expected but I am intermittently receiving the following exception that occurs at the timeout interval I have specified:

    WARNING:   Error invoking requestDestroyed method on ServletRequestListener org.jboss.weld.servlet.WeldListener
java.lang.NullPointerException
    at org.jboss.weld.context.AbstractBoundContext.deactivate(AbstractBoundContext.java:71)
    at org.jboss.weld.context.http.HttpRequestContextImpl.deactivate(HttpRequestContextImpl.java:70)
    at org.jboss.weld.servlet.WeldListener.requestDestroyed(WeldListener.java:154)
    at org.apache.catalina.core.StandardContext.fireRequestDestroyedEvent(StandardContext.java:5261)
    at org.apache.catalina.core.StandardHostValve.postInvoke(StandardHostValve.java:255)
    at org.apache.catalina.connector.Request.errorDispatchAndComplete(Request.java:4484)
    at org.apache.catalina.connector.Request.asyncTimeout(Request.java:4424)
    at org.apache.catalina.connector.Request.processTimeout(Request.java:4458)
    at org.apache.catalina.connector.Request.access$000(Request.java:156)
    at org.apache.catalina.connector.Request$6.onTimeout(Request.java:4302)
    at org.glassfish.grizzly.http.server.Response$SuspendTimeout.onTimeout(Response.java:2024)
    at org.glassfish.grizzly.http.server.Response$DelayQueueWorker.doWork(Response.java:2073)
    at org.glassfish.grizzly.http.server.Response$DelayQueueWorker.doWork(Response.java:2068)
    at org.glassfish.grizzly.utils.DelayedExecutor$DelayedRunnable.run(DelayedExecutor.java:158)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

The servlet definition is my web.xml is as follows:

<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value/>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

An example of one of my Spring MVC endpoints is:

@RequestMapping(value = "/general", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public DeferredResult<String> processGeneralDocuments(@RequestBody DocumentsRequestBody requestBody) {

    DeferredResult<String> result = new DeferredResult<>(appConfig.getDefaultRestTimeout());

    documentsServiceBridge.general(result, requestBody.getDocuments());

    return result;

}

The implementation for the general method of the DocumentsStoreBridge TypedActor is as follows:

@Override
public void general(DeferredResult<String> result, List<AbstractDocument> documents) {
    LOG.debug("Processing {} general documents...", documents.size());

    try {
        result.setResult(documents.size() + " general documents accepted.");
        LOG.debug("DeferredResult set");
        for (AbstractDocument document : documents) {
            documentStore.get().getActorRef().tell(document, TypedActor.context().self());
            LOG.debug("{} document sent to {}", document.get_id(), documentStore.get().getActorType());
        }
    } catch (Exception e) {
        result.setErrorResult(e);
    }

}

As you can see in the DocumentsStoreBridge implementation I am setting the result of the DeferredResult almost immediately, so would expect that to complete the asynchronous request.

What actually happens, intermittently, is that the result is set correctly, and the flow of my program continues, however the asynchronous request is not completed and therefore the client receives a HTTP 500 error when the request times out.

Any help with this is greatly appreciated.

nickebbitt
  • 1,711
  • 1
  • 13
  • 13
  • I do not know much about Spring MVC, but as a wild guess, is it using ThreadLocals internally? – Endre Varga Aug 27 '14 at 13:14
  • Not that I'm aware of. AFIK the Spring MVC layer exposing the REST endpoints to the dispatcher servlet will be making use of the HTTP thread pool and my code then hands the DeferredResult off to the Akka actor which is defined to use the default config which is a fork-join executor. I'm not making any specific configuration changes to how threads should be used, which may in itself be the problem, I'm just unsure at present why the behaviour would be intermittent. – nickebbitt Aug 27 '14 at 14:34
  • 1
    I'm wondering if the answer to this question is related: http://stackoverflow.com/questions/24258951/jee6-long-polling-webservlet-exception-after-calling-asynccontextcomplete – nickebbitt Aug 28 '14 at 08:41

1 Answers1

0

This issue seems to be resolved now following an upgrade to GlassFish 4.1, I imagine the newer version of WELD packaged with 4.1 contained the fix

nickebbitt
  • 1,711
  • 1
  • 13
  • 13