Giriş
Açıklaması şöyle.
While DeferredResult is used to produce a single result, a ResponseBodyEmitter can be used to send multiple objects where each object is written with a compatible HttpMessageConverter
Açıklaması şöyle. Spring'e ait olmayan bir thread varsa kullanılır
A controller method can also return a DeferredResult to complete processing in a thread not known to Spring MVC. For example reacting to a JMS or an AMQP message, a Redis notification, and so on.
Kullanım
Eğer timeout istiyorsak şöyle yaparız
# Asynchronous request timeoutspring.mvc.async.request-timeout=2000
Örnek
Spring dokümantasyonundaki örnek şöyle. setResult() metodu mutlaka başka bir thread içinden çağrılmalı
@GetMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
DeferredResult<String> deferredResult = new DeferredResult<>();
// Save the deferredResult somewhere..
return deferredResult;
}
// From some other thread...
deferredResult.setResult(data);
Örnek
Şöyle yaparız. Burada iş Fork Join Thread Pool içinde çalıştırılıyor.
@GetMapping("/async")
@ResponseBody
public DeferredResult<String> async() {
DeferredResult<String> deferredResult = new DeferredResult<>();
CompletableFuture.supplyAsync(() -> {
// Perform asynchronous processing here
return "Hello, async world!";
}).whenCompleteAsync((result, throwable) -> {
if (throwable != null) {
deferredResult.setErrorResult(throwable);
} else {
deferredResult.setResult(result);
}
});
return deferredResult;
}
Örnek
Şöyle yaparız. Burada iş Fork Join Thread Pool içinde çalıştırılıyor.
@Override
public DeferredResult pull(Long previousId, String username) {
DeferredResult result = createPollingResult(previousId, username);
CompletableFuture.runAsync(() -> {
// this is where you encapsulate your db transaction
List<MessageDTO> messages = messageService.findRecents(previousId, username);
if (messages.isEmpty()) {
pollingResults.putIfAbsent(username, result);
} else {
result.setResult(messages);
}
});
return result;
}
constructor - milliseconds
Örnek
Şöyle yaparız
DeferredResult<ResponseEntity<?>> defResult = new DeferredResult<>(500L);
onCompletion metodu
Örnek
Şöyle yaparız
DeferredResult<?> defResult = ...;
defResult.onCompletion(new Runnable() {
public void run() {
...
});
defResult.onTimeout(new Runnable() {
public void run() {
...
});
setErrorResult metodu
Örnek
Şöyle yaparız
DeferredResult<ResponseEntity<?>> defResult = new DeferredResult<>(500L);
defResult.onTimeout(new Runnable() {
public void run() {
defResult.setErrorResult(ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT)
.body("Request timeout occurred.")));)
});
setResult metodu
Örnek
Şöyle yaparız.
@GetMapping(value = "/math/square")
public DeferredResult<Integer> computeSquare(@RequestParam("x") int x) {
DeferredResult<Integer> deferredResult = new DeferredResult<>();
new Thread(() -> { // normally, you would probably use a thread pool
// here's where the "heavy logic" takes place
...
deferredResult.setResult(x * x);
}).start();
return deferredResult;
}
Örnek - ForkJoin
Şöyle yaparız
@RestControllerpublic class AsyncDeferredController {private final TaskService taskService = ...;@Autowiredpublic AsyncDeferredController(TaskService taskService) {this.taskService = taskService;}@RequestMapping(value = "/deferred", method = RequestMethod.GET, produces = "text/html")public DeferredResult<String> executeSlowTask() {DeferredResult<String> deferredResult = new DeferredResult<>();CompletableFuture.supplyAsync(taskService::execute).whenCompleteAsync((result, throwable) -> deferredResult.setResult(result));return deferredResult;}}
Örnek - ExecutorService
Şöyle yaparız
ExecutorService executorService = Executors.newFixedThreadPool(10);@RequestMapping("/hello_v1")public DeferredResult<String> hello_v1() {// Set timeoutDeferredResult<String> deferredResult = new DeferredResult<>(7000L);// The callback method will be executed when the asynchronous thread processing endsdeferredResult.onCompletion(() -> {log.info ("end of asynchronous thread processing");});// The method will time out if the callback execution time exceeds the settingdeferredResult.onTimeout(() -> {log.info ("asynchronous thread timeout");// Set return resultdeferredResult.setErrorResult("timeout error");});deferredResult.onError(throwable -> {log.error (throwable);// Set return resultdeferredResult.setErrorResult("other error");});executorService.submit(() -> {try {TimeUnit.SECONDS.sleep(5);deferredResult.setResult("hello_v1");// Set return result} catch (Exception e) {e.printStackTrace();// If the asynchronous method has an internal exceptiondeferredResult.setErrorResult("error");}});log.info ("servlet thread processing ended");return deferredResult;}
Örnek - RxJava
Şöyle yaparız.
@RequestMapping(value = "/download/{templateName:.+}")
public DeferredResult<ResponseEntity> download(@PathVariable final String templateName,
@RequestParam final Map<String, Object> args) {
final DeferredResult<ResponseEntity> result = new DeferredResult<>();
try {
// it returns a RxJava Observable
final ReportService reportService = getReportService(templateName);
reportService.process(templateName, args).subscribe(new Consumer<byte[]>() {
public void accept(byte[] bytes) throws Exception {
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", MEDIA_TYPE_SPREADSHEET));
header.setContentDispositionFormData("attachment", templateName);
InputStreamResource resource = new InputStreamResource(
new ByteArrayInputStream(bytes));
result.setResult(ResponseEntity.ok().headers(header).body(resource));
}
}, new Consumer<Throwable>() {
public void accept(Throwable e) throws Exception {
result.setResult(ResponseEntity.badRequest().build());
// ...
}
});
} catch (Exception e) {
result.setResult(ResponseEntity.badRequest().build());
// ...
}
return result;
}
Hiç yorum yok:
Yorum Gönder