多くの並列要求を処理する非同期REST APIがあります。いくつかの現時点で50件の要求(この数字は常に多少異なります)周りの処理を終えた後、私は次のエラーメッセージ・スタックを取得:java.lang.IllegalStateException:非同期REST API
java.lang.IllegalStateException: Cannot forward after response has been committed
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:321) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:395) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:349) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:412) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:158) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:222) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) [tomcat-embed-core-8.5.4.jar:8.5.4]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.4.jar:8.5.4]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_91]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_91]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.4.jar:8.5.4]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
2016-07-29 16:36:28.505 ERROR 7040 --- [nio-8090-exec-2] o.a.c.c.C.[Tomcat].[localhost] : Exception Processing ErrorPage[errorCode=0, location=/error]
私は、このエラーで一日strugellingた...問題は、私がいることですその起源を理解していない。私それはExecuter
とは何かを持っているので、次のように私はそれを構成しても:
@Configuration
@SpringBootApplication
@EnableAsync
public class AppConfig {
@Bean
public javax.validation.Validator localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
@Bean
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(500);
executor.setMaxPoolSize(1000);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}
public static void main(String[] args) {
SpringApplication.run(AppConfig.class, args);
}
}
しかし、問題がまだ存在します。誰かが私にこの問題の理由とその対処方法を説明できるなら、大いに感謝します。
UPDATE:
ホワイトレーベルのエラーページ
このアプリケーションは/エラーのための 明示的なマッピングを持っていない、あなたはこれを見ているように、次のエラーが返され、特に
フォールバック。
:
金7月29日16時36分28秒は、CEST 2016Thereは、これはコードです
予期しないエラーが利用可能(タイプ=内部サーバー エラー、状況= 500).NOのメッセージでしたCONTROLLER
@RestController
@RequestMapping("/test")
public class SController {
private static long maxConcurrentRequests = 0;
@Autowired
Validator validator;
@Autowired
SAnalyzer analyzer;
/**
* Non-blocking processing
* @param docId
* @param document
* @return
*/
@RequestMapping(value = "/{docId}/getAnnotation", method = RequestMethod.GET)
public DeferredResult<Annotations> getAnnotation(@PathVariable String docId,
@RequestParam(value = "document", defaultValue = "{'id':'1','title':'bla-bla','abstract':'bla-bla','text':'bla-bla'}") String document) {
LOGGER.info("Logging output to console");
long reqId = lastRequestId.getAndIncrement();
long concReqs = concurrentRequests.getAndIncrement();
LOGGER.info("{}: Start non-blocking request #{}", concReqs, reqId);
SRequest srequest = new SRequest(SRequest.TYPE_ANNOTATION, docId, document, 1);
this.validateRequest(srequest);
// Initiate the processing in another thread
DeferredResult<Annotations> response = new DeferredResult<>();
analyzer.getAnnotation(reqId, concurrentRequests, srequest,response);
LOGGER.info("{}: Processing of non-blocking request #{} leave the request thread", concReqs, reqId);
// Return to let go of the precious thread we are holding on to...
return response;
}
private void validateRequest(SRequest request) {
DataBinder binder = new DataBinder(request);
binder.setValidator(validator);
binder.validate();
if (binder.getBindingResult().hasErrors()) {
throw new BadSysRequestException(binder.getBindingResult().toString());
}
}
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
class BadSysRequestException extends RuntimeException {
public BadSysRequestException(String message) {
super("Bad request '" + message + "'.");
}
}
TASK
@Async
@Override
public void getAnnotation(long reqId, AtomicLong concurrentRequests, SRequest request, DeferredResult<Annotations> deferredResult)
{
this.deferredResultAnnotations = deferredResult;
this.concurrentRequests = concurrentRequests;
long concReqs = this.concurrentRequests.getAndDecrement();
if (deferredResult.isSetOrExpired()) {
LOGGER.warn("{}: Processing of non-blocking request #{} already expired {}", concReqs, reqId, request.getDocument());
} else {
// result = make some heavy calculations
deferredResultAnnotations.setResult(result);
LOGGER.info("{}: Processing of non-blocking request #{} done {}", concReqs, reqId, request.getDocument());
}
}
可能な複製:http://stackoverflow.com/questions/22743803/servlet-with-java-lang-illegalstateexception-cannot-forward-after-response-has –
@PiotrWilkin:私は 'forward'を使用していません。コードスニペットを一瞬で投稿します。 – HackerDuck
@PiotrWilkin:スレッドを更新しました。あなたが指定したスレッドでは、エラーの理由は、 '応答がクライアントにコミットされる前にフォワードが呼び出されます'として指定されます。しかし、私は自分のコードで 'forward'をどこで使うのか分かりません...特に、Xリクエストがうまく処理され、その時だけ問題が出てくる理由を知ることができません。 – HackerDuck