2

I have a scenario where n threads from an executor thread pool call different web services but all threads should finish their task within a specified time limit else all the pool threads should quit processing their task and return back to their executors pool.

The code I have written works well but the only scenario which is bothering me is that I am not able cancel the already started task i.e a thread waiting for an external web service response.

I understand that future.cancel(true) can not help me achieve this but is there any way I can achieve what I am looking for?

I can not afford to wait for a web service response indefinitely with a pools thread. Thanks in advance !

    public class CallProductServiceTask implements Callable<Object>{

      public Object call(){
          // Call to product service
          // For SOAP Client 
          ProductRequest productRequest = new ProductRequest("prodId"); 
          ProductResponse response = (ProductResponse)webServiceTemplate.marshalSendAndReceive(productRequest); 
           // For REST Client 
          ResponseEntity<ProductResponse> response = restTemplate.exchange(productResourceUrl, HttpMethod.POST, productRequest, ProductResponse.class); 
      }
    }

    class Test{

       ExecutorService executor = Executors.newFixedThreadPool(2);

       public static void main(String args[]){
          Future ft = executor.submit(new CallProductServiceTask());
          try{
             Object result = ft.get(3, TimeUnit.SECONDS);
          } catch (TimeoutException e) {
                boolean c = future.cancel(true);
                System.out.println("Timeout " + c);
          } catch (InterruptedException | ExecutionException e) {
                 System.out.println("interrupted");
          }
         System.out.println("END");
      }
    }
Jaraws
  • 581
  • 1
  • 7
  • 24
  • `// Call to product service` need to be _interruptible_. – Boris the Spider Mar 18 '18 at 14:00
  • what does `// Call to product service` look like? – Andrew Tobilko Mar 18 '18 at 14:20
  • It's like as shown here. // For SOAP Client ProductRequest productRequest = new ProductRequest("prodId"); ProductResponse response = (ProductResponse) webServiceTemplate.marshalSendAndReceive(productRequest); // For REST Client ResponseEntity response = restTemplate.exchange(productResourceUrl, HttpMethod.POST, productRequest, ProductResponse.class); – Jaraws Mar 18 '18 at 14:38
  • Please let me know if I am not right with the design or is there any other right way to meet this scenario? – Jaraws Mar 18 '18 at 14:47
  • if you are using posix thread, there should be a cancel function to execute on the thread id, for example in C there is a `pthread_cancel( pthread_t *tid)` , this function cancels a thread from executing – 0.sh Mar 18 '18 at 16:16

1 Answers1

2

I believe your problem is managing a request to the product service. You won't be worrying about interrupting task execution if you properly configure a read timeout for each request.

Here you will find how to set a read timeout for both WebServiceTemplate and RestTemplate:

How to set read timeout in WebServiceTemplate?
How to set read timeout in RestTemplate?

I will write some pseudocode for the RestTemplate-based approach. (I don't remember what exception is thrown with WebServiceTemplate. Though, the idea remains the same.)

CallProductServiceTask#call:

try {
    final ResponseEntity<?> response = restTemplate.exchange(...);

    return parseResponse(response);
} catch (RestClientException e) {
    final Throwable cause = e.getCause();

    if (cause != null && cause instanceof SocketTimeoutException) {
        throw new BusinessLogicException(cause);
    }
}

Test.main:

try {
    future.get();
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    final Throwable cause = e.getCause();

    if (cause != null && cause instanceof BusinessLogicException) {
        System.out.println("The task was interrupted...");
    }
}
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • Hello Andrew, many thanks for your advice. I think from the use case perspective your advice has certainly helped me here. – Jaraws Mar 20 '18 at 13:08