0 Replies Latest reply on Feb 26, 2018 3:49 PM by jangerritsen

    Writing async JAX-RS services with Wildfly 11 with weld development mode active

    jangerritsen

      I started to develop a new JavaEE application where I provide several REST services using JAX-RS

       

      For my experiments I used a simple test Service:

       

      @ApplicationScoped
      @Path("service")

      @Produces(MediaType.APPLICATION_JSON)

      @Consumes(MediaType.APPLICATION_JSON)

      public class RestService {

       

         @Resource
         ManagedExecutorService mes;

         @Path("get")

         @GET
         public void get(@Suspended AsyncResponse ar) {

                mes.execute(

                     () -> {

                          ar.resume(Response.ok("response").build());
                     }

                );
         }

      }

      Trying to use the async approach, I always got an error in my request:

      RESTEASY003320: Failed processing arguments of public void RestService.get(javax.ws.rs.container.AsyncResponse)

       

      Looking in the logs, I saw that the root cause is:

      Caused by: java.lang.IllegalStateException: UT010026: Async is not supported for this request, as not all filters or Servlets were marked as supporting async

      at io.undertow.servlet//io.undertow.servlet.spec.HttpServletRequestImpl.startAsync(HttpServletRequestImpl.java:961)

      at org.jboss.resteasy.resteasy-jaxrs//org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest$Servlet3ExecutionContext.setupAsyncContext(Servlet3AsyncHttpRequest.java:336)

      at org.jboss.resteasy.resteasy-jaxrs//org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest$Servlet3ExecutionContext.suspend(Servlet3AsyncHttpRequest.java:324)

      at org.jboss.resteasy.resteasy-jaxrs//org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest$Servlet3ExecutionContext.suspend(Servlet3AsyncHttpRequest.java:318)

      at org.jboss.resteasy.resteasy-jaxrs//org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest$Servlet3ExecutionContext.suspend(Servlet3AsyncHttpRequest.java:312)

      at org.jboss.resteasy.resteasy-jaxrs//org.jboss.resteasy.core.AsynchronousResponseInjector.inject(AsynchronousResponseInjector.java:38)

      at org.jboss.resteasy.resteasy-jaxrs//org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:92)

      ... 59 more

       

      With further debugging I found this code in io.undertow.servlet.handlers.FilterHandler

      public FilterHandler(final Map<DispatcherType, List<ManagedFilter>> filters, final boolean allowNonStandardWrappers, final HttpHandler next) {

         this.allowNonStandardWrappers = allowNonStandardWrappers;
         this.next = next;
         this.filters = new EnumMap<>(filters);
         Map<DispatcherType, Boolean> asyncSupported = new EnumMap<>(DispatcherType.class);
         for(Map.Entry<DispatcherType, List<ManagedFilter>> entry : filters.entrySet()) {

            boolean supported = true;
         for(ManagedFilter i : entry.getValue()) {

            if(!i.getFilterInfo().isAsyncSupported()) {

               supported = false; // <-- marked as not supporting async
               break;
            }

         }

         asyncSupported.put(entry.getKey(), supported);
         }

         this.asyncSupported = asyncSupported;
      }

       

      Using inspection to find the culprit in the list I found:

      i = {ManagedFilter@16278} "ManagedFilter{filterInfo=FilterInfo{filterClass=class org.jboss.weld.probe.ProbeFilter, name='weld-probe-filter'}}"

           filterInfo = {FilterInfo@16326} "FilterInfo{filterClass=class org.jboss.weld.probe.ProbeFilter, name='weld-probe-filter'}"

                filterClass = {Class@11698} "class org.jboss.weld.probe.ProbeFilter"

                name = "weld-probe-filter"

                instanceFactory = {UndertowDeploymentInfoService$6@16330}

                initParams = {HashMap@16331}  size = 0

                asyncSupported = false

       

      Using Google and searching around I found this hint:

      https://docs.jboss.org/weld/reference/latest/en-US/html/configure.html#config-dev-mode

      To disable the monitoring entirely set org.jboss.weld.probe.invocationMonitor.excludeType and org.jboss.weld.probe.eventMonitor.excludeType properties to .*.

       

      But setting the filters did not help. I did not investigate why. I guess they are still loaded, not executed for my request but the check for async support is done globally on server initialization.

       

      The only way to get the async mechanism running was to disable the weld development mode globally.

      <subsystem xmlns="urn:jboss:domain:weld:4.0" development-mode="false"/>

       

       

      Having the development mode disabled is not a problem for me at the moment, but it took me several hours to find the cause of my problem and a fitting workaround.

      I thought someone here might be interested to find a better solution, or at least, someone else having the same problem can now google the error message and hopefully find my workaround