我想就在 Vert.x 中编写模板处理代码的最佳方法提出建议,以避免ClosedByInterruptException
。我们处理的模板并不复杂,但Vert.x code sample中建议的方法偶尔会产生下面提到的异常。
Vert.x 代码如下所示:
engine.getThymeleafTemplateEngine().clearTemplateCache();
fileKeyObservable.toList().doOnError(e -> LOGGER.error("Failed to fetch journey documentation files", e)).subscribe(fileKeys -> {
routingContext.put("yamlFiles", generateYamlFiles(fileKeys));
engine.render(routingContext, "templates/index.html", resource -> {
if (resource.succeeded()) {
LOGGER.debug("Successfully generated template");
routingContext.response().putHeader(CONTENT_TYPE, TEXT_HTML_VALUE).end(resource.result());
} else {
LOGGER.error("Failed to render template, cause: {}", resource.cause());
routingContext.fail(resource.cause());
}
});
});
这里是异常堆栈跟踪:
2018-05-21 14:14:44,964 [RxIoScheduler-19] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][RxIoScheduler-19] Exception processing template "templates/index.html": io.vertx.core.VertxException: java.nio.channels.ClosedByInterruptException
io.vertx.core.VertxException: io.vertx.core.VertxException: java.nio.channels.ClosedByInterruptException
at io.vertx.ext.web.impl.Utils.readFileToString(Utils.java:363) ~[vertx-web-3.5.1.jar:3.5.1]
at io.vertx.ext.web.impl.Utils.readFileToString(Utils.java:352) ~[vertx-web-3.5.1.jar:3.5.1]
at io.vertx.ext.web.templ.impl.ThymeleafTemplateEngineImpl$ResourceTemplateResolver.computeTemplateResource(ThymeleafTemplateEngineImpl.java:177) ~[vertx-web-templ-thymeleaf-3.5.1.jar:3.5.1]
at org.thymeleaf.templateresolver.AbstractTemplateResolver.resolveTemplate(AbstractTemplateResolver.java:356) ~[thymeleaf-3.0.0.RELEASE.jar:3.0.0.RELEASE]
at org.thymeleaf.engine.TemplateManager.resolveTemplate(TemplateManager.java:840) ~[thymeleaf-3.0.0.RELEASE.jar:3.0.0.RELEASE]
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:608) ~[thymeleaf-3.0.0.RELEASE.jar:3.0.0.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1087) ~[thymeleaf-3.0.0.RELEASE.jar:3.0.0.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1056) ~[thymeleaf-3.0.0.RELEASE.jar:3.0.0.RELEASE]
at io.vertx.ext.web.templ.impl.ThymeleafTemplateEngineImpl.render(ThymeleafTemplateEngineImpl.java:105) ~[vertx-web-templ-thymeleaf-3.5.1.jar:3.5.1]
at io.vertx.ext.web.templ.TemplateEngine.render(TemplateEngine.java:48) ~[vertx-web-3.5.1.jar:3.5.1]
at com.theglue.requesthandler.DynamicIndexDocumentationHandler.lambda$handle$2(DynamicIndexDocumentationHandler.java:40) ~[request-handler-latest.jar:?]
at rx.internal.util.ActionSubscriber.onNext(ActionSubscriber.java:39) [rxjava-1.3.8.jar:1.3.8]
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:134) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onNext(OnSubscribeDoOnEach.java:101) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.producers.SingleDelayedProducer.emit(SingleDelayedProducer.java:102) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.producers.SingleDelayedProducer.setValue(SingleDelayedProducer.java:85) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorToObservableList$1.onCompleted(OperatorToObservableList.java:98) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onCompleted(OnSubscribeMap.java:97) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$InnerSubscriber.onCompleted(OperatorMerge.java:860) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$InnerSubscriber.onCompleted(OperatorMerge.java:860) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$InnerSubscriber.onCompleted(OperatorMerge.java:860) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.onCompleted(OperatorMerge.java:281) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onCompleted(OnSubscribeMap.java:97) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorMerge$MergeSubscriber.onCompleted(OperatorMerge.java:281) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onCompleted(OnSubscribeMap.java:97) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.checkTerminated(OperatorObserveOn.java:281) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:216) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230) [rxjava-1.3.8.jar:1.3.8]
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) [rxjava-1.3.8.jar:1.3.8]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_171]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_171]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_171]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_171]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_171]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
Caused by: io.vertx.core.VertxException: java.nio.channels.ClosedByInterruptException
是否有更好的方法来编写模板处理代码,以便我们不会获得线程中断的异常? Vert.x 示例代码似乎提出了与我们相同的方法。