title: Spring DeferredResult onCompletion not called from test cases
body: <p>I have a comet(long polling) <code>Controller</code> call, which takes in some ids and <code>puts</code> then into a blocking queue if no calculation for that id is running, for a <code>Consumer</code> to <code>take</code> from the <code>queue</code> and perform computations on these ids. I am using <code>Springs</code> <code>DeferredResult</code> for asynch support.</p>
  
  <p>I maintain a <code>Map</code> of <code>DeferredResult</code> and the corresponding ids that were received in a request. When the calculations for a id are complete in the consumer thread I check for this id in the <code>Map</code> and set the associated <code>DeferredResults</code> <code>setResult</code> which send the response back to the client.</p>
  
  <p>In the <code>Controller</code> method I have an <code>onCompletion</code> callback of <code>DeferredResult</code> which removes this <code>DeferredResult</code> object from the <code>Map</code>.</p>
  
  <p>The client then removes this id from its request and sends the remaining ids. As as example say the client send initially ids "1,2,3" they all got inserted into <code>BlockingQueue</code> and say the calculation for id "2" was finished earlier, then its <code>DeferredResults</code> <code>setResult</code> will be set, which will return the response to the client. And through the callback this <code>DeferredResult</code> will be removed from the <code>Map</code>. And the client in the next request will send ids "1, 3". </p>
  
  <p>Now all works fine, but when I started writing test cases for this the <code>onCompletion</code> callback is never called. I even tried it in the springs official examples it does not seem to be called even there. Is there a way to call it, or something is incorrect in my implementation.</p>
  
  <p>This is my <code>Controller</code> method:</p>
  
  <pre><code>@RequestMapping(value = "views/getLongPollingGraphData", method = RequestMethod.GET, headers = "Accept=application/json")
  @ResponseBody
  public DeferredResult&lt;WebServiceResponse&gt; getLongGraphData(
          HttpServletRequest request,
          @RequestParam(value = "ids") String ids) 
  {
      //create a default response in case, when no result has been calculated till timeout
      WebServiceResponse awrDefault = new WebServiceResponse();
  
      //set time out this DeferredResult, after 5 seconds 
      final DeferredResult&lt;WebServiceResponse&gt; deferredResult = new DeferredResult&lt;WebServiceResponse&gt;(5000L, awrDefault);
  
      //logic to set in blocking queue
      //mMapOfDeferredResultAndViews.put(deferredResult, listOfViews.keySet());
  
      deferredResult.onCompletion(new Runnable() {
          @Override
          public void run() 
          {
              mMapOfDeferredResultAndViews.remove(deferredResult);
          }
      });
  
      return deferredResult;
  }
  </code></pre>
  
  <p>Below is a part of the test case:</p>
  
  <pre><code>@Before
  public void setup() 
  {
      this.mockMvc = webAppContextSetup(this.wac).build();
  }
  
  @Test
  public void testLongPollGraphData()
  {
      try
      {         
          String ids = "22,23,25";
          List&lt;Integer&gt; idList = convertStringToList(ids);
  
          while(idList.size() &gt; 0)
          {
              MvcResult mvcResult = this.mockMvc.perform(get("/views/getLongPollingGraphData")
                  .contentType(MediaType.APPLICATION_JSON)
                  .param("ids", ids)          
                  .andReturn();
  
              this.mockMvc.perform(asyncDispatch(mvcResult));
              WebServiceResponse result = (WebServiceResponse)mvcResult.getAsyncResult();
  
              if(result != null)
              {
                  EJSChartsData chartsData = (EJSChartsData)result.getResponse();
                  if(chartsData != null &amp;&amp; chartsData.getViewId() != -1)
                  {
                      int viewId = chartsData.getViewId();
                      idList.remove((Integer)viewId);
                      ids = idList.toString().replace("[", "").replace("]", "");
                  }
              }
          }
      }
      catch(Exception e)
      {
          fail(e.toString());
      }
  }
  </code></pre>
  
  <p>The <code>Controller</code> method is called and I receive the response as expected, but as the <code>onCompletion</code> callback is never called my logic of calling the method again by removing the id takes a hit as the <code>Map</code> holds on the past <code>DeferredResult</code>.</p>
  
  <p><strong>Update</strong></p>
  
  <p>The test class annotations are:</p>
  
  <pre><code>@RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration(locations = { "/test-context.xml" })
  @WebAppConfiguration
  @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
  @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  </code></pre>
  
  <p>I have another observation, the call to <code>getLongPollingGraphData</code> is not completed, i.e. it does not wait for the specified timeout of 5 seconds and returns immediately causing the <code>result</code> to be <code>null</code>. I read about it and the recommendation is to add <code>.andExpect(request().asyncResult("Expected output"))</code> to <code>mockMvc</code> object.</p>
  
  <p>But this is the whole point of my test case, I want the result to be calculated and returned so that I can resend a request modifying my ids variable based on the response received.</p>