[ 
https://issues.apache.org/jira/browse/CAMEL-8675?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jostein Gogstad updated CAMEL-8675:
-----------------------------------
    Description: 
Processors attached to aggregators can not throw exceptions, they will be 
swallowed. This makes it impossible to propagate exceptions from camel to, for 
instance, a CXF endpoint or custom JAX-WS service.

This route and test illustrates the problem:

{code:java|title=AggregatorBug.java}
public class AggregatorBug extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("direct:start")
            .routeId(getClass().getSimpleName())
            .aggregate().header("cheese")
            .aggregationStrategy(new GroupedExchangeAggregationStrategy())
            .completionSize(1)
            .process(new Processor() {
                @Override
                public void process(Exchange exchange) throws Exception {
                    throw new RuntimeException();
                }
            });
    }
}
{code}

{code:java|title=AggregatorBugTest.java}
public class AggregatorBugTest extends CamelTestSupport {

    @EndpointInject(uri = "mock:beforeException")
    protected MockEndpoint beforeException;

    @Override
    public boolean isUseAdviceWith() {
        return true;
    }


    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new AggregatorBug();
    }

    @Override
    protected void doPostSetup() throws Exception {
        
context.getRouteDefinition(AggregatorBug.class.getSimpleName()).adviceWith(context,
 new AdviceWithRouteBuilder() {
            @Override
            public void configure() throws Exception {
                
weaveByType(ProcessDefinition.class).before().to("mock:beforeException");
            }
        });
        context.start();
    }

    @Test
    public void exceptions_are_swallowed() throws Exception {
        try {
            template.sendBodyAndHeader("direct:start", 42, "cheese", "foo");
            fail("Expected exception");
        } catch (CamelExecutionException e) {
            beforeException.expectedMessageCount(1);
        }

    }
}
{code}

>From what I can see, the problem is located in 
>[AggregatorProcessor|https://github.com/apache/camel/blob/camel-2.12.x/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java#L247]
> (github link). The output from {{doAggregate}} is ignored, even though it 
>contains the exchange with the exception. The exchange that is used from here 
>on out is the original input to the route, not the aggregated output. 

The only way I can see that would trigger the exception would be to add a 
custom errorHandler that re-throwed the exception. Unfortunately this is also 
impossible. The {{errorHandler}} on {{AggregatorProcessor}} is set in the 
constructor, and there is no API to set the errorHandler from 
{{AggregatorDefinition}}. The errorHandler set on the route is also ignored by 
{{AggregatorProcessor}}.

This problem has been reported earlier in CAMEL-1546. The proposed solution 
with using a seda route is not satisfactory for cxf endpoints since the calling 
thread would return.

  was:
Processors attached to aggregators can not throw exceptions, they will be 
swallowed. This makes it impossible to propagate exceptions from camel to, for 
instance, a CXF endpoint or custom JAX-WS service.

This route and test illustrates the problem:

{code:java|title=AggregatorBug.java}
public class AggregatorBug extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("direct:start")
            .routeId(getClass().getSimpleName())
            .aggregate().header("cheese")
            .aggregationStrategy(new GroupedExchangeAggregationStrategy())
            .completionSize(1)
            .process(new Processor() {
                @Override
                public void process(Exchange exchange) throws Exception {
                    throw new RuntimeException();
                }
            });
    }
}
{code}

{code:java|title=AggregatorBugTest.java}
public class AggregatorBugTest extends CamelTestSupport {

    @EndpointInject(uri = "mock:beforeException")
    protected MockEndpoint beforeException;

    @Override
    public boolean isUseAdviceWith() {
        return true;
    }


    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new AggregatorBug();
    }

    @Override
    protected void doPostSetup() throws Exception {
        
context.getRouteDefinition(AggregatorBug.class.getSimpleName()).adviceWith(context,
 new AdviceWithRouteBuilder() {
            @Override
            public void configure() throws Exception {
                
weaveByType(ProcessDefinition.class).before().to("mock:beforeException");
            }
        });
        context.start();
    }

    @Test
    public void exceptions_are_swallowed() throws Exception {
        try {
            template.sendBodyAndHeader("direct:start", 42, "cheese", "foo");
            fail("Expected exception");
        } catch (CamelExecutionException e) {
            beforeException.expectedMessageCount(1);
        }

    }
}
{code}

>From what I can see, the problem is located in 
>[AggregatorProcessor|https://github.com/apache/camel/blob/camel-2.12.x/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java#L247]
> (github link). The output from {{doAggregate}} is ignored, even though it 
>contains the exchange with the exception. The exchanged that is used from here 
>on out is the original input to the route, not the aggregated output. 

The only way I can see that would trigger the exception would be to add a 
custom errorHandler that re-throwed the exception. Unfortunately this is also 
impossible. The {{errorHandler}} on {{AggregatorProcessor}} is set in the 
constructor, and there is no API to set the errorHandler from 
{{AggregatorDefinition}}. The errorHandler set on the route is also ignored by 
{{AggregatorProcessor}}.

This problem has been reported earlier in CAMEL-1546. The proposed solution 
with using a seda route is not satisfactory for cxf endpoints since the calling 
thread would return.


> Aggregators swallow exceptions
> ------------------------------
>
>                 Key: CAMEL-8675
>                 URL: https://issues.apache.org/jira/browse/CAMEL-8675
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>    Affects Versions: 2.12.2
>            Reporter: Jostein Gogstad
>              Labels: aggregator
>
> Processors attached to aggregators can not throw exceptions, they will be 
> swallowed. This makes it impossible to propagate exceptions from camel to, 
> for instance, a CXF endpoint or custom JAX-WS service.
> This route and test illustrates the problem:
> {code:java|title=AggregatorBug.java}
> public class AggregatorBug extends RouteBuilder {
>     @Override
>     public void configure() throws Exception {
>         from("direct:start")
>             .routeId(getClass().getSimpleName())
>             .aggregate().header("cheese")
>             .aggregationStrategy(new GroupedExchangeAggregationStrategy())
>             .completionSize(1)
>             .process(new Processor() {
>                 @Override
>                 public void process(Exchange exchange) throws Exception {
>                     throw new RuntimeException();
>                 }
>             });
>     }
> }
> {code}
> {code:java|title=AggregatorBugTest.java}
> public class AggregatorBugTest extends CamelTestSupport {
>     @EndpointInject(uri = "mock:beforeException")
>     protected MockEndpoint beforeException;
>     @Override
>     public boolean isUseAdviceWith() {
>         return true;
>     }
>     @Override
>     protected RouteBuilder createRouteBuilder() throws Exception {
>         return new AggregatorBug();
>     }
>     @Override
>     protected void doPostSetup() throws Exception {
>         
> context.getRouteDefinition(AggregatorBug.class.getSimpleName()).adviceWith(context,
>  new AdviceWithRouteBuilder() {
>             @Override
>             public void configure() throws Exception {
>                 
> weaveByType(ProcessDefinition.class).before().to("mock:beforeException");
>             }
>         });
>         context.start();
>     }
>     @Test
>     public void exceptions_are_swallowed() throws Exception {
>         try {
>             template.sendBodyAndHeader("direct:start", 42, "cheese", "foo");
>             fail("Expected exception");
>         } catch (CamelExecutionException e) {
>             beforeException.expectedMessageCount(1);
>         }
>     }
> }
> {code}
> From what I can see, the problem is located in 
> [AggregatorProcessor|https://github.com/apache/camel/blob/camel-2.12.x/camel-core/src/main/java/org/apache/camel/processor/aggregate/AggregateProcessor.java#L247]
>  (github link). The output from {{doAggregate}} is ignored, even though it 
> contains the exchange with the exception. The exchange that is used from here 
> on out is the original input to the route, not the aggregated output. 
> The only way I can see that would trigger the exception would be to add a 
> custom errorHandler that re-throwed the exception. Unfortunately this is also 
> impossible. The {{errorHandler}} on {{AggregatorProcessor}} is set in the 
> constructor, and there is no API to set the errorHandler from 
> {{AggregatorDefinition}}. The errorHandler set on the route is also ignored 
> by {{AggregatorProcessor}}.
> This problem has been reported earlier in CAMEL-1546. The proposed solution 
> with using a seda route is not satisfactory for cxf endpoints since the 
> calling thread would return.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to