[英]Using CompletableFuture with @Async returns an empty response for spring boot API
Here is my controller. 这是我的控制器。 I used postman to test if it's working but I am getting an empty response.
我使用邮递员来测试它是否正常工作,但是我收到了一个空的答复。 I used
@EnableAsync
in application configuration and @Async
on the service. 我用
@EnableAsync
在应用程序配置和@Async
的服务。 If I remove @Async
on service layer it works but it doesn't run asynchronously. 如果我在服务层上删除
@Async
,它可以工作,但不会异步运行。
@ApiOperation(value = "search person by passing search criteria event/title/role/host/is_current", response = ElasticSearchResultData.class)
@RequestMapping(value = "/async2/searchPerson", produces = "application/json", method = RequestMethod.POST)
public @ResponseBody CompletableFuture<ElasticSearchResultData> searchPersonAsync2(@RequestBody SearchCriteriaTo criteriaForDivNetFolderTo,
HttpServletRequest request, HttpServletResponse response){
LOGGER.info("searchPerson controller start");
SearchCriteria searchCriteria = criteriaForDivNetFolderTo.getSearchCriteria();
if (Util.isNull(searchCriteria))
throw new IllegalArgumentException("search criteria should not be null.");
try {
CompletableFuture<ElasticSearchResultData> searchPerson = cubService.searchPersonAsync2(criteriaForDivNetFolderTo);
ObjectMapper mapper = new ObjectMapper();
LOGGER.info("search Person "+mapper.writeValueAsString(searchPerson));
return searchPerson;
} catch (Exception e) {
LOGGER.error("Exception in searchPersonAsync controller "+e.getMessage());
}
return null;
}
Service 服务
@Async
@Override
public CompletableFuture<ElasticSearchResultData> searchPersonAsync2(SearchCriteriaTo searchCriteriaForDivNetFolderTo) {
Long start = System.currentTimeMillis();
LOGGER.info(":in searchPerson");
CompletableFuture<ElasticSearchResultData> completableFuture = new CompletableFuture<>();
ElasticSearchResultData searchResultData = null;
SearchCriteria searchCriteria = searchCriteriaForDivNetFolderTo.getSearchCriteria();
try {
LOGGER.info("************ Started searchPerson by criteria ************");
StringBuilder url = new StringBuilder();
url.append(equilarSearchEngineApiUrl)
.append(focusCompanySearchUrl)
.append("/")
.append("searchPerson")
.append("?view=").append(VIEW_ALL)
.append("&isProcessing=true");
LOGGER.debug("Calling equilar search engine for focused company search, URL : " + url);
LOGGER.info(searchCriteria.toString());
String output = null;
if (redisEnable != null && redisEnable) {
output = cacheDao.getDataFromRestApi(url.toString(), RequestMethod.POST.name(), searchCriteria);
} else {
output = Util.getDataFromRestApi(url.toString(), RequestMethod.POST.name(), searchCriteria);
}
if (!Util.isEmptyString(output)) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
searchResultData = objectMapper.readValue(output,
objectMapper.getTypeFactory().constructType(ElasticSearchResultData.class));
}
List<PersonSearchDetails> newPersonDetails = new ArrayList<PersonSearchDetails>();
if (!Util.isNull(searchResultData) && !Util.isNullOrEmptyCollection(searchResultData.getPersonDetails())
&& !Util.isNullOrEmptyCollection(searchCriteriaForDivNetFolderTo.getNetworkFoldersData())) {
for (PersonSearchDetails personDetail : searchResultData.getPersonDetails()) {
String logoUrl = null;
if(!Util.isNull(searchCriteria.getTargetFolderId())){
List<DiversityNetworkFolderTo> filteredFolderTos = searchCriteriaForDivNetFolderTo
.getNetworkFoldersData()
.stream()
.filter(folder -> folder.getId()
.longValue() == searchCriteria
.getTargetFolderId())
.collect(Collectors.toList());
logoUrl = getLogoUrl(personDetail.getPersonId(),
filteredFolderTos);
} else {
logoUrl = getLogoUrl(personDetail.getPersonId(),
searchCriteriaForDivNetFolderTo.getNetworkFoldersData());
}
personDetail.setLogoUrl(logoUrl);
newPersonDetails.add(personDetail);
}
searchResultData.setPersonDetails(newPersonDetails);
}
completableFuture.complete(searchResultData);
return completableFuture;
} catch (Exception e) {
completableFuture.completeExceptionally(e);
LOGGER.error(
" ************** Error in proccessing searchPerson by criteria ************** " + e.getMessage());
}
Long end = System.currentTimeMillis();
LOGGER.info(TIME_DURATION+(end - start)+"ms");
return null;
}
It would be good to read more about async processing. 最好阅读有关异步处理的更多信息。 javadocs are usually a great start!
通常, javadocs是一个不错的开始!
If you really want to get the result from a Future method, you need to wait for it. 如果您真的想从Future方法获得结果,则需要等待。
There is a method public T get()
method in the CompletableFuture
API to wait for wait for the result to be created and return the result once it's done. CompletableFuture
API中有一个方法public T get()
方法来等待创建结果,并在完成后返回结果。
If your job is to search a database for the result and then return it - you will still have to wait for it async is not much help in here. 如果您的工作是在数据库中搜索结果,然后返回它-您仍然必须等待它异步在这里并没有太大帮助。 It would help you if you had to make multiple things at the same time, eg a call to DB, a web service and something else at the same time, then you can create an array of futures and wait for all of them to complete.
如果您必须同时进行多项操作(例如,对数据库的调用,Web服务和其他操作),这将对您有所帮助,那么您可以创建一系列期货并等待所有这些完成。
Or, let's say you're creating a POST
method, so you can quickly validate the input and send to store to DB async while quickly returning the response to UI and hoping that your async method will be completed in another thread and not returning any errors to UI. 或者,假设您正在创建
POST
方法,因此您可以快速验证输入并发送到数据库异步存储,同时快速将响应返回给UI,并希望您的异步方法将在另一个线程中完成并且不会返回任何错误到UI。
This is a great technique when you know what you're doing, but think if & when you really need it before using it. 当您知道自己在做什么时,但在使用前先考虑是否真正需要它时,这是一种很棒的技术。
The short way to "fix" this is: “修复”此问题的简短方法是:
CompletableFuture<ElasticSearchResultData> searchPerson = cubService.searchPersonAsync2(criteriaForDivNetFolderTo);
ElasticSearchResultData result = searchPerson.get();
ObjectMapper mapper = new ObjectMapper();
LOGGER.info("search Person "+mapper.writeValueAsString(result));
return result;
( and obviously change the method return signature ) (并且显然更改方法的返回签名)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.