How to set a timeout on a POST request using Spring RestTemplate? - spring-boot

I want to set a timeout on the process of sending a POST request via Spring RestTemplate. For example, if request is not finished within X sec for whatever reasons, I want it to throw an exception and stop execution/release resources, if possible.
Initially, I tried to use a HttpComponentsClientHttpRequestFactory, but didn't succeed and degraded to SimpleClientHttpRequestFactory. Now I just want to make it work with SimpleClientHttpRequestFactory in all cases and then try a more complex solution.
I have the following configuration:
#Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(3_000);
requestFactory.setReadTimeout(30_000);
return new RestTemplate(requestFactory);
}
The I use it as follows:
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "text/xml;charset=UTF-8");
HttpEntity<String> requestEntity = new HttpEntity<>(xmlMsgAsString, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
I have one destination server, which is currently unreachable, and I have a bunch of XML messages that I need to POST to this server. With the code as above, for majority of messages it works as expected, it throws the following exception after 30 sec:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://X:Y/Z": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:445)
...
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:55)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
... 18 common frames omitted
However, for one particular message it's stuck for ~955 secs and then throws the following exception:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://X:Y/Z": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:445)
...
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketException: Unexpected end of file from server
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:851)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:55)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
... 26 common frames omitted
The previous successfully thrown after 30 sec messages and the last one are similar XML messages and destination is the same. The only difference I thought of was the size of messages, the last one is ~204KB, while all previous ones are much smaller. Why the last exception occurs and how to set time restriction on this case?
Spring Boot 2.1.10 running on Jetty

Related

Getting Kafka error- java.util.concurrent.ExecutionException: org.springframework.kafka.core.KafkaProducerException: Failed to send

I am getting the error in Kafka. While sending the message on the topic
Here is the code for sending message on topic.
#Override
public void sendMessage(User user) {
ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(user);
future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
#Override
public void onSuccess(SendResult<String, Object> result) {
}
#Override
public void onFailure(Throwable e) {
}
});
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
throw new SystemException("Error sending message to topic " + channelConfiguration.getTopic(), e);
**Getting following error here**
}
}
Here is the error I am getting while sending message on topic
Caused by: java.util.concurrent.ExecutionException: org.springframework.kafka.core.KafkaProducerException: Failed to send; nested exception is org.apache.kafka.common.errors.TimeoutException: Topic user_event not present in metadata after 60000 ms.
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:na]
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) ~[na:na]
at org.springframework.util.concurrent.SettableListenableFuture.get(SettableListenableFuture.java:119) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at com.test.common.messenger.kafka.sender.KafkaMessageSender.sendMessage(KafkaMessageSender.java:60) ~[classes/:na]
... 55 common frames omitted
Caused by: org.springframework.kafka.core.KafkaProducerException: Failed to send; nested exception is org.apache.kafka.common.errors.TimeoutException: Topic loyalty_event not present in metadata after 60000 ms.
at org.springframework.kafka.core.KafkaTemplate.lambda$buildCallback$4(KafkaTemplate.java:424) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
at org.apache.kafka.clients.producer.KafkaProducer.doSend(KafkaProducer.java:930) ~[kafka-clients-2.3.1.jar:na]
at org.apache.kafka.clients.producer.KafkaProducer.send(KafkaProducer.java:856) ~[kafka-clients-2.3.1.jar:na]
at org.springframework.kafka.core.DefaultKafkaProducerFactory$CloseSafeProducer.send(DefaultKafkaProducerFactory.java:592) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
at org.springframework.kafka.core.KafkaTemplate.doSend(KafkaTemplate.java:404) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
at org.springframework.kafka.core.KafkaTemplate.send(KafkaTemplate.java:254) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
at com.test.common.messenger.kafka.sender.KafkaMessageSender.sendMessage(KafkaMessageSender.java:45) ~[classes/:na]
... 55 common frames omitted
Caused by: org.apache.kafka.common.errors.TimeoutException: Topic user_event not present in metadata after 60000 ms.
Does anyone knows about this?
Topic user_event not present in metadata after 60000 ms.
Do you have the topic user_event?
If not you need to create it or else configure Kafka admin to create topic automatically.

Spring AMQP Outbound Adapter behavior when exchange not found

I have a spring integration code that connects a JMS listener (that listens to a mq series local queue)
<int-jms:message-driven-channel-adapter>
and forwards the message to a rabbitmq (not controlled by me) via a
<int-amqp:outbound-channel-adapter>
I am trying to keep this transactional meaning that if the rabbitmq did not receive the message I want to keep it in the MQ series local queue.
However I noticed that if the exchange that was mentioned in the rabbitmq configurations did not exist I see in my logs this line:
ERROR (CachingConnectionFactory.java:292) - Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'xxx' in vhost 'xxx', class-id=60, method-id=40)
But my message disappears for the mq series local queue.
What shall i do do make it retry to send the message if the rabbitmq broker fails or if the exchange does not exists?
Thanks for your help,
My configuration:
<int-jms:message-driven-channel-adapter
id="x.y.z" channel="channel-in"
error-channel="errorChannel" header-mapper="jmsIntegrationHeaderMapper"
acknowledge="transacted" destination-name="a.b.c" />
<int:channel id="channel-in">
</int:channel>
<int:header-enricher input-channel="channel-in"
output-channel="channel-out">
<int:header name="url"
expression="'amqp://${amqp.user}#${amqp.host}:${amqp.port}/${amqp.vhost}'"></int:header>
</int:header-enricher>
<int:channel id="channel-out">
</int:channel>
<int-amqp:outbound-channel-adapter
channel="channel-out" amqp-template="amqpTemplate"
routing-key="crd" mapped-request-headers="*" exchange-name="${amqp.exchange}">
</int-amqp:outbound-channel-adapter>
<rabbit:connection-factory id="amqpConnectionFactory" addresses="${amqp.host}:${amqp.port}"
cache-mode="CONNECTION"
channel-cache-size="25"
username="${amqp.user}"
password="${amqp.pass}"
virtual-host="${amqp.vhost}"/>
<rabbit:template id="amqpTemplate"
connection-factory="amqpConnectionFactory" mandatory="true" channel-transacted="true"/>
Unlike JMS, publishing to RabbitMQ is asynchronous (which is why it's generally faster), so the failure for a missing exchange is reported on a different thread; you can add a listener to get the notification instead of it just being logged.
You can enable transactions template.setChannelTransacted(true); and then the failure will be reported on the publishing thread because it will be blocked waiting for the reply from the txCommit() when the IO error occurs.
However, transactions are quite expensive so can hurt performance.
For other errors (e.g. exchange exists, but no route to a queue), you can use publisher confirms and returns but, again, waiting for a confirmation for each individual message published will slow down performance.
EDIT
You should get an exception on txCommit.
Caused by: org.springframework.amqp.AmqpIOException: java.io.IOException
at org.springframework.amqp.rabbit.connection.RabbitUtils.commitIfNecessary(RabbitUtils.java:107) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.doSend(RabbitTemplate.java:2003) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.lambda$send$3(RabbitTemplate.java:865) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1841) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1784) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.send(RabbitTemplate.java:864) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertAndSend(RabbitTemplate.java:927) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertAndSend(RabbitTemplate.java:921) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at com.example.So47454769Application.lambda$0(So47454769Application.java:29) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:780) [spring-boot-2.0.0.M7.jar:2.0.0.M7]
... 5 common frames omitted
Caused by: java.io.IOException: null
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:126) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:122) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:144) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.ChannelN.txCommit(ChannelN.java:1519) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.ChannelN.txCommit(ChannelN.java:52) ~[amqp-client-5.0.0.jar:5.0.0]
at org.springframework.amqp.rabbit.support.PublisherCallbackChannelImpl.txCommit(PublisherCallbackChannelImpl.java:588) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler.invoke(CachingConnectionFactory.java:981) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
at com.sun.proxy.$Proxy60.txCommit(Unknown Source) ~[na:na]
at org.springframework.amqp.rabbit.connection.RabbitUtils.commitIfNecessary(RabbitUtils.java:104) ~[spring-rabbit-2.0.2.BUILD-SNAPSHOT.jar:2.0.2.BUILD-SNAPSHOT]
... 14 common frames omitted
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'junk' in vhost '/', class-id=60, method-id=40)
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:494) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:288) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:138) ~[amqp-client-5.0.0.jar:5.0.0]
... 24 common frames omitted
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'junk' in vhost '/', class-id=60, method-id=40)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:504) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:346) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:178) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:111) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQConnection.readFrame(AMQConnection.java:643) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQConnection.access$300(AMQConnection.java:47) ~[amqp-client-5.0.0.jar:5.0.0]
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:581) ~[amqp-client-5.0.0.jar:5.0.0]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]

Connection Timed out issue while consuming REST API service

I have developed a microservice using Reactive WebFlux of Spring 5. In this, using webClient, I'm trying to consume another REST API service. Everything works fine when I'm using my personal home network however I always get connection timed out error whenever I try to consume this same REST service using my microservice while working in my office.
I suspect it has something to do with the firewall or proxy in my office network. I have already disabled the windows firewall in my machine but still not working. Any advise on this issue.
Following is the code snippet:
#RestController
public class MyRestController {
private final WebClient webClient;
public TweetController(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://mockapi.demo.com").build();
}
#GetMapping("/get-customers")
public Mono<String> someRestCall(String name) {
System.out.println("****************** /get-customers *******************");
return this.webClient
.get()
.uri("/catalogs")
.retrieve()
.bodyToMono(String.class);
}
Error:
ERROR 17996 --- [ctor-http-nio-3] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request
[GET http://localhost:8080/get-customers]
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection
timed out: no further information: test.usdemo.xyz.com/92.54.41.24:443
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
~[na:1.8.0_171] at
sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
~[na:1.8.0_171] at
io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:325)
~[netty-transport-4.1.24.Final.jar:4.1.24.Final] at
io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340)
~[netty-transport-4.1.24.Final.jar:4.1.24.Final] at
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:633)
~[netty-transport-4.1.24.Final.jar:4.1.24.Final] at
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
~[netty-transport-4.1.24.Final.jar:4.1.24.Final] at
io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
~[netty-transport-4.1.24.Final.jar:4.1.24.Final] at
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
~[netty-transport-4.1.24.Final.jar:4.1.24.Final] at
io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
~[netty-common-4.1.24.Final.jar:4.1.24.Final] at
java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_171] Caused by:
java.net.ConnectException: Connection timed out: no further
information ... 10 common frames omitted

How to have multiple Camel Rest DSL definitions with Swagger

I am using Camel 2.16.0 with camel-netty4-http, camel-swagger-java and camel-spring-boot in a Spring-boot application. My SpringBootRouter is configured in the following way:
public void configure() {
restConfiguration()
.component("netty4-http")
.bindingMode(RestBindingMode.json)
.dataFormatProperty("prettyPrint", "true")
.host("0.0.0.0")
.contextPath("/")
.port(port)
.apiContextPath("/api-doc")
.apiProperty("api.title", "User API")
.apiProperty("api.version", "1.2.3")
.apiProperty("cors", "true");
rest("/hello").description("Say hello.")
.produces("application/json")
.get().description("Get hello.").route().transform(constant("hello"));
rest("/hi").description("Say hi.")
.produces("application/json")
.get().description("Get hi.").route().transform(constant("hi"));
}
How can I have multiple rest definitions with Swagger? The configuration above gives me just the exception below. However, if I remove the other rest definition rest("/hi") then Swagger is working just fine.
The exception:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.boot.maven.RunMojo$LaunchRunner.run(RunMojo.java:423)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.camel.spring.boot.CamelSpringBootInitializationException: org.apache.camel.FailedToStartRouteException: Failed to start route route4 because of Multiple consumers for the same endpoint is not allowed: Endpoint[http://0.0.0.0:10000/api-doc?httpMethodRestrict=GET]
at org.apache.camel.spring.boot.RoutesCollector.onApplicationEvent(RoutesCollector.java:81)
at org.apache.camel.spring.boot.RoutesCollector.onApplicationEvent(RoutesCollector.java:37)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:775)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:139)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.apache.camel.spring.boot.FatJarRouter.main(FatJarRouter.java:26)
... 6 more
Caused by: org.apache.camel.FailedToStartRouteException: Failed to start route route4 because of Multiple consumers for the same endpoint is not allowed: Endpoint[http://0.0.0.0:10000/api-doc?httpMethodRestrict=GET]
at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRouteConsumers(DefaultCamelContext.java:3473)
at org.apache.camel.impl.DefaultCamelContext.doStartRouteConsumers(DefaultCamelContext.java:3449)
at org.apache.camel.impl.DefaultCamelContext.safelyStartRouteServices(DefaultCamelContext.java:3379)
at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRoutes(DefaultCamelContext.java:3147)
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:3003)
at org.apache.camel.impl.DefaultCamelContext.access$000(DefaultCamelContext.java:172)
at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:2799)
at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:2795)
at org.apache.camel.impl.DefaultCamelContext.doWithDefinedClassLoader(DefaultCamelContext.java:2818)
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:2795)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:2764)
at org.apache.camel.spring.boot.RoutesCollector.onApplicationEvent(RoutesCollector.java:79)
... 17 more
Yeah that is a bug in Apache Camel. I have logged a ticket:
https://issues.apache.org/jira/browse/CAMEL-9247

Spring Integration DSL ErrorHandling

As the title says, I'm looking for a good example on errorHandling within a DSL flow. Specifically, I'm looking to handle errors from a service activator.
Example:
IntegrationFlows.from(Amqp.inboundAdapter(simpleMessageListenerContainer()))
.transform(new JsonToObjectTransformer(AlbumDescriptor.class))
.handle(AlbumDescriptor.class, (p,h) -> transformXml(p))
.transform(new ObjectToJsonTransformer())
.handle(Amqp.outboundAdapter(rabbitTemplate).routingKey("xml-transformed"))
.get();
If my function transformXml(p) throws an exception, how do I make it go to a specific errorChannel.
If an exception is not thrown, everything works just as I want it to.
Currently, if an exceptions is thrown from this function I get the following exception:
2014-09-17 15:26:28.566 WARN 16339 --- [cTaskExecutor-1] s.a.r.l.ConditionalRejectingErrorHandler : Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.listener.ListenerExecutionFailedException: Listener threw exception
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.java:758)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:653)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:576)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.java:78)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.java:161)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.java:1177)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:559)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:950)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:934)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$600(SimpleMessageListenerContainer.java:78)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1045)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.messaging.MessageHandlingException: java.lang.reflect.InvocationTargetException
at org.springframework.integration.dsl.LambdaMessageProcessor.processMessage(LambdaMessageProcessor.java:125)
at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:71)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:109)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:94)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:260)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:241)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:205)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:199)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:177)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:109)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:94)
at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:98)
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter.access$400(AmqpInboundChannelAdapter.java:44)
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$1.onMessage(AmqpInboundChannelAdapter.java:90)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:650)
... 10 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.integration.dsl.LambdaMessageProcessor.processMessage(LambdaMessageProcessor.java:122)
... 41 common frames omitted
Caused by: com.amazonaws.services.s3.model.AmazonS3Exception: The specified key does not exist. (Service: Amazon S3; Status Code: 404; Error Code: NoSuchKey; Request ID: 7029FF03D01CFB95)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1053)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:662)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:428)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:290)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3655)
at com.amazonaws.services.s3.AmazonS3Client.getObject(AmazonS3Client.java:1132)
at com.amazonaws.services.s3.AmazonS3Client.getObject(AmazonS3Client.java:1004)
at com.emusic.indiegestion.integration.flows.AlbumTransformFlowConfig.transformXml(AlbumTransformFlowConfig.java:67)
at com.emusic.indiegestion.integration.flows.AlbumTransformFlowConfig.lambda$0(AlbumTransformFlowConfig.java:49)
at com.emusic.indiegestion.integration.flows.AlbumTransformFlowConfig$$Lambda$1/2142893855.handle(Unknown Source)
... 46 common frames omitted
Actually there is no difference if it is DSL or raw XML Spring Integration config.
Amqp.inboundAdapter() provides .errorChannel() option as well as <amqp:inbound-channel-adapter> provides error-channel attribute.
As I say in the manual DSL does the same as all other Spring Integration configuration variants. So, Error Handling here is the same too.
More info on the matter: http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/configuration.html#namespace-errorhandler

Resources