Разбираюсь с apache camel
и в частности с ErrorHandler
.
<errorHandler id="deadError" type="DeadLetterChannel" deadLetterUri="file:data/fault" useOriginalMessage="true"/>
<errorHandler id="logError" type="LoggingErrorHandler" level="WARN"/>
<errorHandler id="noError" type="NoErrorHandler"/>
<dataFormats>
<jaxb id="jaxb" contextPath="ru.camel"/>
</dataFormats>
<route id="requestRoute" errorHandlerRef="noError">
<from uri="file:data/input"/>
<unmarshal ref="jaxb"/>
<process ref="WsCaller"/>
<to uri="direct:startSoap"/>
<marshal ref="jaxb"/>
<convertBodyTo type="String"/>
<log message="FileName=${in.header.fileName}"/>
<to uri="file:data/output?fileName=${in.header.fileName}"/>
</route>
<route id="soapRoute" errorHandlerRef="noError" handleFault="true">
<from uri="direct:startSoap"/>
<log message="Вызов метода ${in.header.operationName}"/>
<setHeader headerName="operationName">
<constant>calcSumm</constant>
</setHeader>
<to uri="cxf:bean:externalWS"/>
<process ref="WsResult"/>
</route>
Из каталога data/input читается файл содержащий данные которые будут использоваться для вызова Web-сервиса (простой веб сервис складывающий два числа). Ответ Web-сервиса разбирается и в конце формируется файл с ответом в каталоге data/input.
Когда я выключаю web-сервис при его вызове возникает Exception:
org.apache.cxf.interceptor.Fault: Could not send Message.
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:64)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:416)
at org.apache.camel.component.cxf.CxfProducer.process(CxfProducer.java:120)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.interceptor.HandleFaultInterceptor.process(HandleFaultInterceptor.java:42)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:91)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:91)
at org.apache.camel.builder.NoErrorHandlerBuilder$1.process(NoErrorHandlerBuilder.java:40)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:62)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:91)
at org.apache.camel.builder.NoErrorHandlerBuilder$1.process(NoErrorHandlerBuilder.java:40)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:454)
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:226)
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:190)
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:175)
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:102)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.ConnectException: ConnectException invoking http://air-aleksej:8080/SimpleWebService/Calculate: Connection refused (Connection refused)
at sun.reflect.GeneratedConstructorAccessor57.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.mapException(HTTPConduit.java:1377)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1361)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:651)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
... 35 more
Исходный файл остается в каталоге и route уходит в бесконечный цикл.
Как с помощью onErrorHandler
можно обойти данную ситуацию. Т.е. я хочу отключить реакцию на недоступный web-сервис, чтобы Camel не регировал на возникшую ошибку и завершал route. Т.е. чтобы исходный файл удалялся.
Как я понимаю noErrorHandle позволяет это сделать, но либо я неправильно понимаю его смысл, или что-то делаю не так.
Полезные ссылки с офф.сайта:
То, что route уходит в бесконечный цикл - это в принципе правильно, конечная цель же не достигнута.
Можно сделать разные варианты по реализации (действия по обработке Exception или try-catch-finaly). Например, удаление файла можно сделать в finally
.
В итоге, предлагаю обернуть вызов web-service в try-catch. И в случае exception выполнить некие действия с файлом в catch.
Примеры в статьях:
Вариант структуры route в Java DSL:
from("direct:start")
.doTry()
.process(new ProcessorFail())
.to("mock:result")
.doCatch(IOException.class, IllegalStateException.class)
.to("mock:catch")
.doFinally()
.to("mock:finally")
.end();
Вариант структуры route в XML:
<route>
<from uri="direct:start"/>
<!-- here the try starts. its a try .. catch .. finally just as regular java code -->
<doTry>
<process ref="processorFail"/>
<to uri="mock:result"/>
<doCatch>
<!-- catch multiple exceptions -->
<exception>java.io.IOException</exception>
<exception>java.lang.IllegalStateException</exception>
<to uri="mock:catch"/>
</doCatch>
<doFinally>
<to uri="mock:finally"/>
</doFinally>
</doTry>
</route>
Дополняю ответ по вопросу: для чего нужен NoErrorHandler
?
Ссылка на офф.описание с примером: Error Handler
NoErrorHandler
- используется для отключения обработчиков ошибок и не более того. Но это не исключает возникновение Exception
со всеми вытекающими последствиями.
Применительно к текущему вопросу, когда требуется удалять файл в любом случае, NoErrorHandler
не применим.
Где применять NoErrorHandler
и зачем он вообще нужен?
Как пишут, это некий 'dummy-error-handler', когда разработчик хочет забить на все ошибки и в своем no-transacted
маршруте не хочет их обрабатывать по какой-то причине.
Как делать правильно или "NoErrorHandler must die".
Стандартный подход - это реализовать обработчик ошибок по требуемому набору Exceptions
.
Примерно так:
onException(ConnectException.class)
.bean(MyProcessorForFileDelete())
.handled(true);
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Необходимо получить джсон, который находится по ссылке https://swapgg/api/inventory/bot
Если Java используется в основном для back-end, то что использовать для front-end?
Есть функция foo, которая возвращает массив barБудет ли одинакова последовательность работы у цикла foreach, если в качестве иттерируемого объекта...