java - 没有从测试用例中调用 Spring DeferredResult onCompletion

标签 java spring spring-mvc asynchronous

我有一个 comet(长轮询)Controller 调用,它接受一些 id 并 puts 然后进入阻塞队列,如果没有运行该 id 的计算,对于一个 Consumerqueuetake 并对这些 id 执行计算。我正在使用 Springs DeferredResult 来支持异步。

我维护一个 MapDeferredResult 和请求中收到的相应 ID。当 id 的计算在消费者线程中完成时,我在 Map 中检查此 id 并设置关联的 DeferredResults setResult 发送响应返回给客户端。

Controller 方法中,我有一个 DeferredResultonCompletion 回调,它从 map

然后客户端从它的请求中删除这个 id 并发送剩余的 id。例如,客户端发送最初的 id“1,2,3”,它们都被插入到 BlockingQueue 中,并表示 id“2”的计算较早完成,然后是 DeferredResults setResult 将被设置,这将向客户端返回响应。通过回调,此 DeferredResult 将从 Map 中删除。下一个请求中的客户端将发送 ids“1、3”。

现在一切正常,但是当我开始为此编写测试用例时,从未调用 onCompletion 回调。我什至在 springs 官方示例中尝试过它,即使在那里似乎也没有被调用。有没有办法调用它,或者我的实现中有什么地方不正确。

这是我的 Controller 方法:

@RequestMapping(value = "views/getLongPollingGraphData", method = RequestMethod.GET, headers = "Accept=application/json")
@ResponseBody
public DeferredResult<WebServiceResponse> 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<WebServiceResponse> deferredResult = new DeferredResult<WebServiceResponse>(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;
}

部分测试用例如下:

@Before
public void setup() 
{
    this.mockMvc = webAppContextSetup(this.wac).build();
}

@Test
public void testLongPollGraphData()
{
    try
    {         
        String ids = "22,23,25";
        List<Integer> idList = convertStringToList(ids);

        while(idList.size() > 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 && chartsData.getViewId() != -1)
                {
                    int viewId = chartsData.getViewId();
                    idList.remove((Integer)viewId);
                    ids = idList.toString().replace("[", "").replace("]", "");
                }
            }
        }
    }
    catch(Exception e)
    {
        fail(e.toString());
    }
}

Controller 方法被调用并且我收到了预期的响应,但是由于 onCompletion 回调从未被调用我通过删除 id 再次调用该方法的逻辑需要Map 保留了过去的 DeferredResult

更新

测试类注解是:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/test-context.xml" })
@WebAppConfiguration
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)

我还有另一个观察,对 getLongPollingGraphData 的调用没有完成,即它没有等待指定的 5 秒超时并立即返回导致 result 。我读到了它,建议是将 .andExpect(request().asyncResult("Expected output")) 添加到 mockMvc 对象。

但这就是我的测试用例的重点,我希望计算并返回结果,以便我可以根据收到的响应重新发送修改我的 ids 变量的请求。

最佳答案

您使用的是哪个版本的 Spring? 我打开了SPR-13615对于类似的情况,它在 4.2.3 中得到修复(影响 4.2.2)。

如果您查看评论,您可以在不更新的情况下解决它

    mvcResult.getRequest().getAsyncContext().complete();

关于java - 没有从测试用例中调用 Spring DeferredResult onCompletion,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39909996/

相关文章:

java - Spring Boot - "Error creating bean with name ' entityManagerFactory'"- 开始

mysql - spring mvc restful web 服务中与额外列的多对多关系获得 StackOverflowerror 等

java - 对 Java 中的 Vigenère 密码实现感到困惑

Java - 检索 JSON 对象值

java - 最少硬币使用算法 Java

java - 我们什么时候应该在 Spring 中使用@Component?

java - 如何在生成文件时处理 Spring Controller 上的异常

java - 为什么我看到不请求 Window.FEATURE_SUPPORT_ACTION_BAR?

java - 内容类型不支持 java Spring

java - Spring项目中多数据库连接问题