1 Reply Latest reply on Aug 18, 2012 3:28 AM by davsclaus

    Camel Java DSL RouteBuilder weirdness when using "this"

    dagobah

      This may not be the best way to accomplish what we are trying to accomplish, but I came across an odd issue, and we worked around it, but I wanted to put it in front of the Fuse/Camel team.

       

      I've run this on the servicemix 4.4.1 ESB distribution and the latest ESB 7 distro with the same results.

       

      What we are trying to do is have a Java DSL RouteBuilder build a route so that when an exception occurs it will either post the message to a custom "dead letter" queue or simply log the exception.

       

      We implemented this by using a Recipient List.  The Recipient List returns the destination as a blank string "", or a "direct:handleBadMessage" depending on the config flag.  The route builder class has the flag directly on it, and it is injected through a setter accessor using blueprint and the OSGi config mechanism.

       

      The route looks like this:

       

       

              onException(Throwable.class)

                  .routeId(ROUTE_EXCEPTION)

                  .to("log:" + ROUTE_EXCEPTION + "?showCaughtException=true&showStackTrace=true")

                  .handled(true)

                  .beanRef("distributedLockBean", "releaseLock")

                  .to("retriesProcessor")

                  .choice()

                      .when(header(HEADER_EXECUTE_RETRY).isNotNull())

                      .marshal(jaxb)

                      .inOnly("activemq:SAVE_VEHICLES")

                      .wireTap(vehicleTrace(VEH_DSE_RETRY_ON_EXCEPTION, null, true)).executorServiceRef("traceLogThreadPool").end()

                  .otherwise()

                      .recipientList().method(this, "getDeadMessageTarget").ignoreInvalidEndpoints()

                      .wireTap(vehicleTrace(VEH_END_ERROR, null, true)).executorServiceRef("traceLogThreadPool").end();

       

      We're using some wiretaps to do some asynchronous trace information to a database, and there is some logic in there to optionally retry by placing the request back into the source queue.

       

      The recipientList line, if you comment it out, and trigger an exception, there is no issue.  If you use a constant instead of a method call, no trouble.  But calling a method on this results in the following stack overflow:

       

      14:44:10,403 | WARN  | r[SAVE_VEHICLES] | JmsMessageListenerContainer      | 94 - org.springframework.jms - 3.0.5.RELEASE | Execution of JMS message listener failed, and no ErrorHandler has been set.

      org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[JmsMessage[JmsMessageID: ID:AUS-ADAIRM-57744-1345232393210-26:2:1:1:2]]

              at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1165)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.impl.DefaultExchange.setException(DefaultExchange.java:287)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.processor.UnitOfWorkProcessor.processAsync(UnitOfWorkProcessor.java:166)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:117)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:78)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:98)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:89)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:69)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:104)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:85)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:91)[93:org.apache.camel.camel-jms:2.8.0.fuse-03-06]

              at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:560)[94:org.springframework.jms:3.0.5.RELEASE]

              at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:498)[94:org.springframework.jms:3.0.5.RELEASE]

              at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467)[94:org.springframework.jms:3.0.5.RELEASE]

              at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)[94:org.springframework.jms:3.0.5.RELEASE]

              at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)[94:org.springframework.jms:3.0.5.RELEASE]

              at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)[94:org.springframework.jms:3.0.5.RELEASE]

              at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:952)[94:org.springframework.jms:3.0.5.RELEASE]

              at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)[:1.6.0_27]

              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)[:1.6.0_27]

              at java.lang.Thread.run(Thread.java:662)[:1.6.0_27]

      Caused by: java.lang.StackOverflowError

              at org.apache.camel.builder.ExpressionBuilder$2.toString(ExpressionBuilder.java:103)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.model.language.ExpressionDefinition.toString(ExpressionDefinition.java:99)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.builder.BinaryPredicateSupport.toString(BinaryPredicateSupport.java:46)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.model.language.ExpressionDefinition.getLabel(ExpressionDefinition.java:225)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.model.WhenDefinition.toString(WhenDefinition.java:53)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.ChoiceDefinition.toString(ChoiceDefinition.java:125)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.OnExceptionDefinition.toString(OnExceptionDefinition.java:119)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.RouteDefinition.toString(RouteDefinition.java:114)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.RoutesDefinition.toString(RoutesDefinition.java:62)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.builder.RouteBuilder.toString(RouteBuilder.java:57)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.language.bean.BeanExpression.toString(BeanExpression.java:58)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at org.apache.camel.model.language.ExpressionDefinition.toString(ExpressionDefinition.java:99)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.RecipientListDefinition.toString(RecipientListDefinition.java:88)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.OtherwiseDefinition.toString(OtherwiseDefinition.java:42)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.ChoiceDefinition.toString(ChoiceDefinition.java:125)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.OnExceptionDefinition.toString(OnExceptionDefinition.java:119)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at java.util.AbstractCollection.toString(AbstractCollection.java:422)[:1.6.0_27]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

              at java.lang.StringBuilder.append(StringBuilder.java:115)[:1.6.0_27]

              at org.apache.camel.model.RouteDefinition.toString(RouteDefinition.java:114)[88:org.apache.camel.camel-core:2.8.0.fuse-03-06]

              at java.lang.String.valueOf(String.java:2826)[:1.6.0_27]

      ...

       

      it repeats from there.  Note the repeating part is the choice/otherwise.  Now my work around was to use another bean, configured as a public final variable in the route builder.

       

      So this works:

       

      protected final DeadLetterConfigBean deadLetterConfigBean = new DeadLetterConfigBean();

       

      ...

       

      .recipientList().method(deadLetterConfigBean, "getDeadMessageTarget").ignoreInvalidEndpoints()

       

      The injection on the route builder is then passed to the bean.  I could have configured the bean directly in blueprint as well, but it is curious to me that a "this" reference fails, but a reference to an object instantiated on "this" is fine.

       

      Can anyone offer a reason to what the problem with using the route builder instance in the recipient list is, but using members of the route builder is okay?  Is this an issue somehow with my choice/otherwise block when "this" is present, or an issue with Camel?

       

      Again, I've worked around the problem, so its not a critical issue, but I thought it might be a Camel issue.

       

      Thanks.

       

      - Tim Stewart.