camel noErrorHandle

367
11 мая 2018, 15:33

Разбираюсь с 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 позволяет это сделать, но либо я неправильно понимаю его смысл, или что-то делаю не так.

Answer 1

Полезные ссылки с офф.сайта:

  1. Error handling in Camel
  2. Try ... Catch ... Finally

То, что route уходит в бесконечный цикл - это в принципе правильно, конечная цель же не достигнута. Можно сделать разные варианты по реализации (действия по обработке Exception или try-catch-finaly). Например, удаление файла можно сделать в finally.

В итоге, предлагаю обернуть вызов web-service в try-catch. И в случае exception выполнить некие действия с файлом в catch.

Примеры в статьях:

  1. On the road to Camel 2.0 - Try Catch Finally
  2. Try, Catch, Finally with Camel

Вариант структуры 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);
READ ALSO
парсинг JSON сайта на java

парсинг JSON сайта на java

Необходимо получить джсон, который находится по ссылке https://swapgg/api/inventory/bot

197
Вопрос про front-end. [Java] [требует правки]

Вопрос про front-end. [Java] [требует правки]

Если Java используется в основном для back-end, то что использовать для front-end?

225
Java цикл foreach

Java цикл foreach

Есть функция foo, которая возвращает массив barБудет ли одинакова последовательность работы у цикла foreach, если в качестве иттерируемого объекта...

199