如何从@Async带注释的方法引发异常

时间:2019-04-05 04:53:38

标签: spring-boot asynchronous spring-async

我有两个模块,一个模块从rest模板调用另一个模块。 (管理员调用notifServer) notifServer有一个用@Async注释的方法。我想在该方法中引发异常,但是管理员无法迅速获得响应,因此无法在admin处捕获异常方法。

我是spring和@Async流程的新手。我尝试将响应正文从NotifServer映射到C CompletableFuture.class。 但是我仍然没有收到错误响应。

此代码来自管理员

ResponseEntity response = fcmRestTemplate.exchange(nsUrl + "/fcm/admin/" + bulkFcmId, HttpMethod.POST,
                    HttpEntityUtils.getHttpEntity(moduleCode), CompletableFuture.class);
            if (response.getStatusCode() != HttpStatus.CREATED && response.getStatusCode() != HttpStatus.ACCEPTED) {
                String errorMessage = ErrorResourceUtil.getErrorMessage((HashMap) response.getBody(),"Unable to send fcm");
                setStatusToFailedByBulkFcmId(bulkFcmId);
                throw new ClientException(errorMessage);
            }

现在这是来自 NotifServer

JobExecution jobExecution = jobLauncher
                    .run(importJob, new JobParametersBuilder()
                    .addString("fullPathFileName", TMP_DIR)
                    .addString("batch_fcm_id", String.valueOf(id))
                    .addLong("time",System.currentTimeMillis())
                    .toJobParameters());
            if(jobExecution.getStepExecutions().stream().map(StepExecution::getStatus).findFirst().get().equals(BatchStatus.ABANDONED)){
             throw new ClientException("INVALID CSV");

这用@Async注释。

那么我有办法在Admin的响应正文中捕获客户端异常吗?

编辑 这是来自notifServer的API

@ResponseStatus(HttpStatus.CREATED)
    @PostMapping(value = "/admin/{bulkFcmId}")
    public void pushFCMByAdmin(@PathVariable Long bulkFcmId) {
        fcmService.sendFcmByAdmin(bulkFcmId, AuthUtil.getCurrentUser());
    }

然后sendFcmByAdmin具有@Async批注。

1 个答案:

答案 0 :(得分:0)

在下面的代码中,您可以提供返回类型而不是CompletableFuture.class作为业务对象。由于您将CompletableFuture.class作为参数传递给交易所,因此它期望响应 返回值 ,类型为CompletableFuture.class。

ResponseEntity response = fcmRestTemplate.exchange(nsUrl + "/fcm/admin/" + bulkFcmId, HttpMethod.POST,
                        HttpEntityUtils.getHttpEntity(moduleCode), CompletableFuture.class);
                if (response.getStatusCode() != HttpStatus.CREATED && response.getStatusCode() != HttpStatus.ACCEPTED) {
                    String errorMessage = ErrorResourceUtil.getErrorMessage((HashMap) response.getBody(),"Unable to send fcm");
                    setStatusToFailedByBulkFcmId(bulkFcmId);
                    throw new ClientException(errorMessage);
                }

除了传递Completable Future之外,您还可以尝试如下创建它吗:

使用异步方法在admin中进行其余模板调用:

@Async
public CompletableFuture<List<BusinessObject>> getResponseAsynchronously(String value) {
    String url = "https://restendpoint.eu/rest/v2/lang/" + value + "?fields=name";
    BusinessObject[] response = restTemplate.getForObject(url, Country[].class);
    return CompletableFuture.completedFuture(Arrays.asList(response));
}

然后在控制器中读取CompletableFuture,如下所示:

@GetMapping("")
public List<String> getAllDataFromRestCall() throws Throwable {

    CompletableFuture<List<BusinessObject>> businessObjectsFuture = countryClient.getResponseAsynchronously("fr");
    List<String> europeanFrenchSpeakingCountries;

            try {
                europeanFrenchSpeakingCountries = new ArrayList<>(businessObjectsFuture
                .get()
                .stream()
                .map(Country::getName)
                .collect(Collectors.toList()));

     } catch (Throwable e) {
       throw e.getCause();
     }

   return europeanFrenchSpeakingCountries;
}