Я использую Spring Boot
[v. 2.1.4.RELEASE] и аннотация @Async
вместе с CompletableFuture
для реализации асинхронных и неблокирующих вызовов.
Я реализовал класс Config для запуска TaskExecutor
, который обеспечит многопоточную среду, а также пару классов Service-Controller, которые реализуют запрос POST.
Config
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Bean(name = "musterExecutor")
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("AppExecutor-");
executor.initialize();
return new ThreadPoolTaskExecutor();
}
}
Класс обслуживания, где Status
- это pojo, используемый для отображения ответа.
Услуги
@Service
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class MusterService<T> {
private static final String request_status = RestURIConstants.STATUS;
private static final String request_execution = RestURIConstants.EXECUTE;
private static final String request_async = Constants.ASYNC;
private static final String DATA_FUSION = Constants.DATA_FUSION;
@Autowired
private RestTemplate restTemplate;
@Async("musterExecutor")
public CompletableFuture<Status> execute(Payload payload) {
HttpHeaders headers = setHeaders();
String input = Constructor.createPayload(payload);
HttpEntity<String> requestEntity = new HttpEntity<String>(input, headers);
Status s = restTemplate.postForObject(execution_url, request_execution, Status.class);
return CompletableFuture.completedFuture(s);
}
@Async("musterExecutor")
public CompletableFuture<Status[]> getStatus() {
log.debug("Sending Status Request");
final String status_url = request_status;
HttpHeaders headers = setHeaders();
HttpEntity<String> requestEntity = new HttpEntity<String>(request_async, headers);
Status[] s = restTemplate.postForObject(status_url, requestEntity, Status[].class);
return CompletableFuture.completedFuture(s);
}
private HttpHeaders setHeaders() {
// code for setting the Headers
return headers;
}
}
вместе с простым
Сервисный интерфейс
public interface GenericService<T> {
public abstract CompletableFuture<Status[]> getStatus();
public abstract CompletableFuture<Status> execute(Payload payload);
}
Контроллер
@RestController
@RequestMapping(path = "/api")
public class MusterController {
@Autowired
private MusterService<Status> musterService;
@RequestMapping(value = "/status", method = RequestMethod.GET)
@ResponseBody
public CompletableFuture<Status[]> status() {
CompletableFuture<Status[]> cf_status = new CompletableFuture<Status[]>();
try {
cf_status = musterService.getStatus();
return cf_status;
} catch (RestClientException e) {
e.printStackTrace();
// TODO: handle exception
}
return cf_status;
}
@RequestMapping(value = "/execute", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
@ResponseBody
public CompletableFuture<Status> execute(@RequestBody Payload payload) throws SchedulerException, IOException {
CompletableFuture<Status> cf_execution_body = new CompletableFuture<Status>();
Status execution_body = new Status();
try {
cf_execution_body = musterService.execute(payload);
execution_body = cf_execution_body.get();
return cf_execution_body;
} catch (RestClientException e) {
log.error("RestClientException:{} \t Cause:{}", e.getMessage(), e.getCause());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return cf_execution_body;
}
}
Экземпляр класса правильно проксируется для запуска потока, но когда я пытаюсь implement
Класс обслуживания с классом интерфейса (aka. public class MusterService<T> implements GenericService<T>
..), он выдает мне следующую ошибку:
Причина:
org.springframework.beans.factory.BeanNotOfRequiredTypeException
Сервис проксируется как новый поток и по какой-то причине не может быть
Autowired
Когда я удаляю implements
, тогда все работает как положено.
ПРИМЕЧАНИЕ: Я поместил аннотацию @EnableAspectJAutoProxy(proxyTargetClass = true)
, чтобы она работала в соответствии с рекомендациями, но она ничего не делает. Как я могу заставить это работать?
Ссылки Stackoverflow: