camelinaction/camelinaction2

11.5.1 Using onWhen - Example does not work

PascalSchumacher opened this issue · 5 comments

The example in section 11.5.1 "Using onWhen" on page 510:

public final class MyHttpUtil {
    public static boolean isIllegalDataError(
        HttpOperationFailedException cause) {
        int code = cause.getStatusCode();
        if (code != 500) {
            return false;
        }
        return "ILLEGAL DATA".equals(cause.getResponseBody().toString());
    }
}

onException(HttpOperationFailedException.class)
    .onWhen(bean(MyHttpUtil.class, "isIllegalData"))
    .handled(true)
    .to("file:/rider/files/illegal");

does not work (at least as with Camel version 2.23.0) as demonstrated by this test:

public class OnWhenBindMethodWithExceptionSubclassParameterTest extends CamelTestSupport {

    public static final class MyHttpUtil {
        public static boolean isIllegalDataError(HttpOperationFailedException cause) {
            int code = cause.getStatusCode();
            if (code != 500) {
                return false;
            }
            return "ILLEGAL DATA".equals(cause.getResponseBody().toString());
        }
    }

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

            public void configure() {
                onException(HttpOperationFailedException.class)
                    .onWhen(bean(MyHttpUtil.class, "isIllegalDataError"))
                    .handled(true)
                    .to("mock:illegal");

                from("seda:start")
                    .process(e -> { 
                        throw new HttpOperationFailedException("", 500, "", "", null, "ILLEGAL DATA");
                    });
            }
        };
    }

    @Test
    public void test() throws Exception {
        getMockEndpoint("mock:illegal").expectedMessageCount(1);

        template.sendBody("seda:start", "Hello World");

        assertMockEndpointsSatisfied();
    }
}

I reported this behavior as https://issues.apache.org/jira/browse/CAMEL-12949 - "onWhen predicate with onException can not bind to method with exception subclass parameter", but the issue was rejected as "Won't Fix". Therefore the error lies with this example.

Discovered that the example works if you annotate the HttpOperationFailedException parameter with @ExchangeException.

This test passes:

public class OnWhenCamelInActionBugTest extends CamelTestSupport {

    public static final class MyHttpUtil {
        public static boolean isIllegalDataError(@ExchangeException HttpOperationFailedException cause) {
            int code = cause.getStatusCode();
            if (code != 500) {
                return false;
            }
            return "ILLEGAL DATA".equals(cause.getResponseBody().toString());
        }
    }

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

            public void configure() {
                onException(HttpOperationFailedException.class)
                    .onWhen(bean(MyHttpUtil.class, "isIllegalDataError"))
                    .handled(true)
                    .to("mock:illegal");

                from("seda:start")
                    .process(e -> { 
                        throw new HttpOperationFailedException("", 500, "", "", null, "ILLEGAL DATA");
                    });
            }
        };
    }

    @Test
    public void test() throws Exception {
        getMockEndpoint("mock:illegal").expectedMessageCount(1);

        template.sendBody("seda:start", "Hello World");

        assertMockEndpointsSatisfied();
    }
}

Thanks for reporting

I added this to the errata

Thanks!

A small nitpick:

The line:

.onWhen(bean(MyHttpUtil.class, "isIllegalData"))

should be changed to:

.onWhen(bean(MyHttpUtil.class, "isIllegalDataError"))

to match the method name MyHttpUtil#isIllegalDataError.

Thanks I just updated the errata with that info as well