[ 
https://issues.apache.org/jira/browse/HTTPCLIENT-2281?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

brian clozel updated HTTPCLIENT-2281:
-------------------------------------
    Description: 
When working on a AsyncExecChain implementation, the "execute" method is tied 
to the lifecycle of the exchange through the AsyncExecCallback that is provided 
to the next element in the chain.

It's not clear how the AsyncExecChain is supposed to be notified of 
cancellations and how it should clear resources. None of the AsyncExecCallback 
contracts are not called when a cancellation occurs.

Given the following sample implementation, that allocates resources when the 
execution starts. The handler is not notified of cancellations and resources 
cannot be cleared as a result.
{code:java}
public class CustomHandler implements AsyncExecChainHandler {

    @Override
    public void execute(HttpRequest request, AsyncEntityProducer 
entityProducer, AsyncExecChain.Scope scope,
            AsyncExecChain chain, AsyncExecCallback asyncExecCallback) throws 
HttpException, IOException {
        
        CustomResource resource = CustomResource.allocate();

        chain.proceed(request, entityProducer, newScope, new 
AsyncExecCallback() {

            @Override
            public AsyncDataConsumer handleResponse(HttpResponse response, 
EntityDetails entityDetails)
                    throws HttpException, IOException {
                // not called in case of cancellation
                resource.clear();
                return asyncExecCallback.handleResponse(response, 
entityDetails);
            }

            @Override
            public void handleInformationResponse(HttpResponse response) throws 
HttpException, IOException {
                // not called in case of cancellation                
                asyncExecCallback.handleInformationResponse(response);          
   
            }

            @Override
            public void completed() {
                // not called in case of cancellation
                resource.clear();
                asyncExecCallback.completed();
            }

            @Override
            public void failed(Exception cause) {
                // not called in case of cancellation
                resource.clear();
                asyncExecCallback.failed(cause);
            }

        });

    }
{code}
Here is a concrete sample using the custom handler:
{code:java}
CustomHandler customHandler = new CustomHandler();
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
  .addExecInterceptorFirst("custom", customHandler)
  .build();
client.start();

final SimpleHttpRequest request = 
SimpleRequestBuilder.get("http://localhost/delay/10";).build();
final Future<SimpleHttpResponse> future = client.execute(request,
    new FutureCallback<SimpleHttpResponse>() {
        @Override
        public void completed(final SimpleHttpResponse response) {
        }

        @Override
        public void failed(final Exception ex) {
        }

        @Override
        public void cancelled() {
          // this method is called but the custom handler is not made aware of 
cancellations
          System.out.println(request + " cancelled");
        }
});
future.cancel(true);
{code}
So far I have used the AsyncExecChain.Scope CancellableDependency and tried to 
wrap it to be notified of cancellations but I'm not sure this is the right 
choice.

  was:
When working on a AsyncExecChain implementation, the "execute" method is tied 
to the lifecycle of the exchange through the AsyncExecCallback that is provided 
to the next element in the chain.

It's not clear how the AsyncExecChain is supposed to be notified of 
cancellations and how it should clear resources. None of the AsyncExecCallback 
contracts are not called when a cancellation occurs.

Given the following sample implementation, that allocates resources when the 
execution starts. The handler is not notified of cancellations and resources 
cannot be cleared as a result.
{code:java}
public class CustomHandler implements AsyncExecChainHandler {

    @Override
    public void execute(HttpRequest request, AsyncEntityProducer 
entityProducer, AsyncExecChain.Scope scope,
            AsyncExecChain chain, AsyncExecCallback asyncExecCallback) throws 
HttpException, IOException {
        
        CustomResource resource = CustomResource.allocate();

        chain.proceed(request, entityProducer, newScope, new 
AsyncExecCallback() {

            @Override
            public AsyncDataConsumer handleResponse(HttpResponse response, 
EntityDetails entityDetails)
                    throws HttpException, IOException {
                // not called in case of cancellation
                resource.clear();
                return asyncExecCallback.handleResponse(response, 
entityDetails);
            }

            @Override
            public void handleInformationResponse(HttpResponse response) throws 
HttpException, IOException {
                // not called in case of cancellation                
                asyncExecCallback.handleInformationResponse(response);          
   
            }

            @Override
            public void completed() {
                // not called in case of cancellation
                resource.clear();
                asyncExecCallback.completed();
            }

            @Override
            public void failed(Exception cause) {
                resource.clear();
                asyncExecCallback.failed(cause);
            }

        });

    }
{code}
Here is a concrete sample using the custom handler:
{code:java}
CustomHandler customHandler = new CustomHandler();
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
  .addExecInterceptorFirst("custom", customHandler)
  .build();
client.start();

final SimpleHttpRequest request = 
SimpleRequestBuilder.get("http://localhost/delay/10";).build();
final Future<SimpleHttpResponse> future = client.execute(request,
    new FutureCallback<SimpleHttpResponse>() {
        @Override
        public void completed(final SimpleHttpResponse response) {
        }

        @Override
        public void failed(final Exception ex) {
        }

        @Override
        public void cancelled() {
          // this method is called but the custom handler is not made aware of 
cancellations
          System.out.println(request + " cancelled");
        }
});
future.cancel(true);
{code}
So far I have used the AsyncExecChain.Scope CancellableDependency and tried to 
wrap it to be notified of cancellations but I'm not sure this is the right 
choice.


> AsyncExecChain is not aware of cancellations
> --------------------------------------------
>
>                 Key: HTTPCLIENT-2281
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2281
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpClient (async)
>    Affects Versions: 5.2.1
>            Reporter: brian clozel
>            Priority: Minor
>
> When working on a AsyncExecChain implementation, the "execute" method is tied 
> to the lifecycle of the exchange through the AsyncExecCallback that is 
> provided to the next element in the chain.
> It's not clear how the AsyncExecChain is supposed to be notified of 
> cancellations and how it should clear resources. None of the 
> AsyncExecCallback contracts are not called when a cancellation occurs.
> Given the following sample implementation, that allocates resources when the 
> execution starts. The handler is not notified of cancellations and resources 
> cannot be cleared as a result.
> {code:java}
> public class CustomHandler implements AsyncExecChainHandler {
>     @Override
>     public void execute(HttpRequest request, AsyncEntityProducer 
> entityProducer, AsyncExecChain.Scope scope,
>             AsyncExecChain chain, AsyncExecCallback asyncExecCallback) throws 
> HttpException, IOException {
>         
>         CustomResource resource = CustomResource.allocate();
>         chain.proceed(request, entityProducer, newScope, new 
> AsyncExecCallback() {
>             @Override
>             public AsyncDataConsumer handleResponse(HttpResponse response, 
> EntityDetails entityDetails)
>                     throws HttpException, IOException {
>                 // not called in case of cancellation
>                 resource.clear();
>                 return asyncExecCallback.handleResponse(response, 
> entityDetails);
>             }
>             @Override
>             public void handleInformationResponse(HttpResponse response) 
> throws HttpException, IOException {
>                 // not called in case of cancellation                
>                 asyncExecCallback.handleInformationResponse(response);        
>      
>             }
>             @Override
>             public void completed() {
>                 // not called in case of cancellation
>                 resource.clear();
>                 asyncExecCallback.completed();
>             }
>             @Override
>             public void failed(Exception cause) {
>                 // not called in case of cancellation
>                 resource.clear();
>                 asyncExecCallback.failed(cause);
>             }
>         });
>     }
> {code}
> Here is a concrete sample using the custom handler:
> {code:java}
> CustomHandler customHandler = new CustomHandler();
> CloseableHttpAsyncClient client = HttpAsyncClients.custom()
>   .addExecInterceptorFirst("custom", customHandler)
>   .build();
> client.start();
> final SimpleHttpRequest request = 
> SimpleRequestBuilder.get("http://localhost/delay/10";).build();
> final Future<SimpleHttpResponse> future = client.execute(request,
>     new FutureCallback<SimpleHttpResponse>() {
>         @Override
>         public void completed(final SimpleHttpResponse response) {
>         }
>         @Override
>         public void failed(final Exception ex) {
>         }
>         @Override
>         public void cancelled() {
>           // this method is called but the custom handler is not made aware 
> of cancellations
>           System.out.println(request + " cancelled");
>         }
> });
> future.cancel(true);
> {code}
> So far I have used the AsyncExecChain.Scope CancellableDependency and tried 
> to wrap it to be notified of cancellations but I'm not sure this is the right 
> choice.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to