首页 > 解决方案 > 在 SEDA 上启用 bridgeErrorHandler 后,onException(Throwable.class) 未处理异常

问题描述

我有以下路线

onException(Throwable.class)
.handled(true)
.process(...)                              --- (A1) Have a shutdown code here.
.rollback();

from("file:D/data/input?fileName=in.txt")
.transacted("required")                    --- (A2) Have JPA Txn Manager and hikari pooled datasource behind the scene
.split(...)
.to("seda:DUMMY?blockWhenFull=true");

from("seda:DUMMY?bridgeErrorHandler=true")
.transacted("required")                    --- (A3) Creating new transaction due to SEDA
.process(...)                              --- (A4) reading from database and doing some computation
.to("file:D:/data/ouput?fileName=out.txt")

我设法在处理文件(in.txt)之间关闭了数据库,因此 HikariDataSource 开始抛出异常。然而,即使在 SEDA 消费者端启用了 bridgeErrorHandler,这些异常也没有被 onException() 子句处理。在日志中,我发现这些异常只是由 TransactionErrorHandler 记录的。您能否帮助在这种情况下如何触发 onException(),以便应用程序可以关闭?

请在下面找到日志:

2020-06-10 18:25:14,314 WARN com.zaxxer.hikari.pool.ProxyConnection [157] [Camel (camel-1) thread #1 - file://D:/data/input] -[TEST1]-[RW_TEST_ROUTE_2]-[3019]-[]- HikariPool-1 - Connection oracle.jdbc.driver.T4CConnection@6eeade6c marked as broken because of SQLSTATE(08006), ErrorCode(17002)
java.sql.SQLRecoverableException: IO Error: Connection reset by peer: socket write error
    at oracle.jdbc.driver.T4CConnection.doCommit(T4CConnection.java:965) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:2401) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:2407) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:366) ~[HikariCP-3.4.1.jar!/:?]
    at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java) ~[HikariCP-3.4.1.jar!/:?]
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:81) ~[hibernate-core-5.4.9.Final.jar!/:5.4.9.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:282) ~[hibernate-core-5.4.9.Final.jar!/:5.4.9.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.9.Final.jar!/:5.4.9.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:534) ~[spring-orm-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744) ~[spring-tx-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:712) ~[spring-tx-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:152) ~[spring-tx-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]
    at org.apache.camel.spring.spi.TransactionErrorHandler.doInTransactionTemplate(TransactionErrorHandler.java:182) ~[camel-spring-3.0.0.jar!/:3.0.0]
    at org.apache.camel.spring.spi.TransactionErrorHandler.processInTransaction(TransactionErrorHandler.java:140) ~[camel-spring-3.0.0.jar!/:3.0.0]
    at org.apache.camel.spring.spi.TransactionErrorHandler.process(TransactionErrorHandler.java:107) ~[camel-spring-3.0.0.jar!/:3.0.0]
    at org.apache.camel.spring.spi.TransactionErrorHandler.process(TransactionErrorHandler.java:116) ~[camel-spring-3.0.0.jar!/:3.0.0]
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:228) ~[camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.processor.Pipeline.doProcess(Pipeline.java:103) ~[camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.processor.Pipeline.lambda$process$1(Pipeline.java:87) ~[camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$3.run(DefaultReactiveExecutor.java:116) [camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:185) [camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59) [camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:87) [camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:228) [camel-base-3.0.0.jar!/:3.0.0]
    at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:454) [camel-file-3.0.0.jar!/:3.0.0]
    at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:223) [camel-file-3.0.0.jar!/:3.0.0]
    at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:186) [camel-file-3.0.0.jar!/:3.0.0]
    at org.apache.camel.support.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:183) [camel-support-3.0.0.jar!/:3.0.0]
    at org.apache.camel.support.ScheduledPollConsumer.run(ScheduledPollConsumer.java:102) [camel-support-3.0.0.jar!/:3.0.0]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_251]
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source) [?:1.8.0_251]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) [?:1.8.0_251]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) [?:1.8.0_251]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_251]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_251]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_251]
Caused by: java.net.SocketException: Connection reset by peer: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method) ~[?:1.8.0_251]
    at java.net.SocketOutputStream.socketWrite(Unknown Source) ~[?:1.8.0_251]
    at java.net.SocketOutputStream.write(Unknown Source) ~[?:1.8.0_251]
    at oracle.net.ns.DataPacket.send(DataPacket.java:209) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.net.ns.NetOutputStream.flush(NetOutputStream.java:215) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:302) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:249) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:171) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.net.ns.NetInputStream.read(NetInputStream.java:89) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:429) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:397) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4C7Ocommoncall.doOCOMMIT(T4C7Ocommoncall.java:73) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    at oracle.jdbc.driver.T4CConnection.doCommit(T4CConnection.java:910) ~[ojdbc7-customized-12.1.0.2.0.jar!/:12.1.0.2.0]
    ... 35 more
2020-06-10 18:25:14,318 WARN org.apache.camel.spring.spi.TransactionErrorHandler [276] [Camel (camel-1) thread #1 - file://D:/data/input] -[TEST1]-[RW_TEST_ROUTE_2]-[3019]-[]- Transaction rollback (0x21f9764) redelivered(false) for (MessageId: ID-RAJUP-1591793597060-0-1 on ExchangeId: ID-RAJUP-1591793597060-0-2) caught: Unable to commit against JDBC Connection; nested exception is org.hibernate.TransactionException: Unable to commit against JDBC Connection
2020-06-10 18:25:14,319 WARN org.apache.camel.component.file.GenericFileOnCompletion [144] [Camel (camel-1) thread #1 - file://D:/data/input] -[TEST1]-[RW_TEST_ROUTE_2]-[3019]-[RW_TEST_ROUTE_2-1]- Rollback file strategy: org.apache.camel.component.file.strategy.GenericFileRenameProcessStrategy@6834b2f3 for file: GenericFile[D:\data\input\in.txt]
2020-06-10 18:25:27,306 WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper [137] [Camel (camel-1) thread #2 - seda://ADPIN] -[TEST1]-[RW_TEST_ROUTE_2]-[3019]-[RW_TEST_ROUTE_2-4]- SQL Error: 0, SQLState: null
2020-06-10 18:25:27,306 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper [142] [Camel (camel-1) thread #2 - seda://ADPIN] -[TEST1]-[RW_TEST_ROUTE_2]-[3019]-[RW_TEST_ROUTE_2-4]- HikariPool-1 - Connection is not available, request timed out after 30000ms.
2020-06-10 18:25:27,307 WARN org.apache.camel.spring.spi.TransactionErrorHandler [276] [Camel (camel-1) thread #2 - seda://ADPIN] -[TEST1]-[RW_TEST_ROUTE_2]-[3019]-[RW_TEST_ROUTE_2-4]- Transaction rollback (0x21f9764) redelivered(false) for (MessageId: ID-RAJUP-1591793597060-0-140 on ExchangeId: ID-RAJUP-1591793597060-0-5227) caught: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection

标签: apache-camelspring-camel

解决方案


我希望我找到了上述行为的原因:

在 SEDA 消费者或任何有能力的消费者上启用 bridgeErrorHandler 会告诉错误处理程序(在我们的例子中是 TransactionErrorHandler,而不是 OnException() 子句)来处理异常。ErrorHandlers 是最后的手段,即如果任何异常没有被 OnException() 子句捕获,那么错误处理程序将在那里处理。正如名称“bridgeErrorHandler”意味着与错误处理程序桥接,因此消息消费期间的任何异常(在我们的例子中来自 SEDA)都将直接触发错误处理程序。感谢 SEDA 消费者端 url 的 'exceptionHandler' 参数给了一个钩子来实现我们想要的功能。

注意:JMS 消费者端 url 曾经有 'bridgeErrorHandler' 选项,但在之后,它被删除了。


推荐阅读