Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-2792

Custom Executor for Service object is ignored by the CXF JAX-WS run-time when Disaptch.invokeAsync is used

    XMLWordPrintableJSON

Details

    Description

      Hi,

      I'm trying to invoke 10000 external services using invokeAsync from my standalone JAX-WS client.
      I set my custom Executor on the Service objects. This executor is a ThreadPool with 3 threads. But it looks like it is ignored completely by the CXF
      run-time. Instead of an Executor, an instance of AutomaticWorkQueueImpl is used.

      BTW, by default, AutomaticWorkQueueImpl is an unbounded queue, so that a few thousands threads are created for processing asynchronous responses. This is of cause problematic and has a big performance impact. By providing the configuration for AutomaticWorkQueueImpl in cxf.xml, the AutomaticWorkQueueImpl can be configured to have a required number of threads and required maximum capacity.

      So, I did some debugging to see, why and where AutomaticWorkQueueImpl is called at all during asynchronous WS invocations using Dispatch.invokeAsync().

      This is the stack trace I got:
      Thread [main] (Suspended (entry into method execute in AutomaticWorkQueueImpl))
      AutomaticWorkQueueImpl.execute(Runnable) line: 247
      HTTPConduit$WrappedOutputStream.handleResponse() line: 2153
      HTTPConduit$WrappedOutputStream.close() line: 1988
      HTTPConduit(AbstractConduit).close(Message) line: 66
      HTTPConduit.close(Message) line: 639
      MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(Message) line: 62
      PhaseInterceptorChain.doIntercept(Message) line: 243
      ClientImpl.invoke(ClientCallback, BindingOperationInfo, Object...) line: 422
      ClientImpl.invokeWrapped(ClientCallback, QName, Object...) line: 371
      DispatchImpl<T>.invokeAsync(T, AsyncHandler<T>) line: 288
      TestAsyncProviderClient.invokeMyDispatch(Dispatch<Source>, Object, AsyncHandler<Source>) line: 298
      TestAsyncProviderClient.testManyAsyncResponses() line: 218
      TestAsyncProviderClient.main(String[]) line: 159

      According to this trace, WS-response processing at the HTTP level is put for the execution on a dedicated working queue in the HTTPConduit.handleResponse method:

      protected void handleResponse() throws IOException {

      handleRetransmits();

      if (outMessage == null || outMessage.getExchange() == null || outMessage.getExchange().isSynchronous())

      { handleResponseInternal(); }

      else {
      Runnable runnable = new Runnable() {
      public void run() {
      try

      { handleResponseInternal(); }

      catch (Exception e)

      { Message inMessage = new MessageImpl(); inMessage.setExchange(outMessage.getExchange()); inMessage.setContent(Exception.class, e); incomingObserver.onMessage(inMessage); }


      }
      };
      WorkQueueManager mgr = outMessage.getExchange().get(Bus.class)
      .getExtension(WorkQueueManager.class);
      AutomaticWorkQueue queue = mgr.getNamedWorkQueue("http-conduit");
      if (queue == null)

      { queue = mgr.getAutomaticWorkQueue(); }


      queue.execute(runnable);
      }
      }

      It is easy to see that Executor set for the JAX-WS Service is not propagated down to the HTTP transoport level, which required dedicated configuration for AutomaticWorkQueue, be it http-conduit queue or automatic work queue.

      For WS-responses at the user-level, i.e. by means of the JAX-WS AsyncHandler handlers, the proper Executor is taken from the Service object.

      See also the discussion on the mailing list:
      http://old.nabble.com/RejectedExecutionException-when-doing-many-invokeAsync-invocations-ts28266640.html

      Attachments

        Activity

          People

            dkulp Daniel Kulp
            romixlev Leo Romanoff
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: