errorHandler + onException

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

errorHandler + onException

dimas
Hi All,

What is the best way to handle the situation when there is a need to automatically adjust  the exchange as part of the error handling and proceed with retry?

For example, there is a route1 that invokes route2 with the 'token' property set. When, during the route2 execution  there is  a failure (401 http error) I want to reset the token property value and make route1 to do the retry (with the updated property).
Here is the sample route that doesn't work (onException never called):

public class ErrorHandlingTest extends CamelTestSupport {

    @Test
    public void runIt() throws Exception {
        template.setDefaultEndpointUri("direct:route2");
        template.sendBodyAndProperty("test", "token", "bad");
    }

    @Override
    protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            public void configure() {

                from("direct:route1")
                        .errorHandler(defaultErrorHandler().maximumRedeliveries(2))
                        .to("direct:route2");

                Predicate got401 = exchangeProperty("CamelExceptionCaught").method("getStatusCode").isEqualTo(401);

                from("direct:route2")
                        .errorHandler(noErrorHandler())
                        .onException(HttpOperationFailedException.class).onWhen(got401).process(e -> {
                            System.out.println("resetting token");
                            e.setProperty("token", "good");}
                            ).end()
                        .choice()
                            .when()
                                .exchange(e -> e.getProperty("token").equals("bad"))
                                .throwException(new HttpOperationFailedException("http://test.com", 401, "not authenticated", "/doIt", new HashMap<>(), "bad token"))
                            .otherwise()
                                .log("token is good");
            }
        };
    }
}

Cheers,
Dmitry
Reply | Threaded
Open this post in threaded view
|

RE: errorHandler + onException

dimas
Sorry, there is some typo te defaultEndpoint should be the top level route : template.setDefaultEndpointUri("direct:route1");

-----Original Message-----
From: Shultz, Dmitry [mailto:[hidden email]]
Sent: Wednesday, May 27, 2020 3:04 PM
To: [hidden email]
Subject: errorHandler + onException

Hi All,

What is the best way to handle the situation when there is a need to automatically adjust  the exchange as part of the error handling and proceed with retry?

For example, there is a route1 that invokes route2 with the 'token' property set. When, during the route2 execution  there is  a failure (401 http error) I want to reset the token property value and make route1 to do the retry (with the updated property).
Here is the sample route that doesn't work (onException never called):

public class ErrorHandlingTest extends CamelTestSupport {

    @Test
    public void runIt() throws Exception {
        template.setDefaultEndpointUri("direct:route2");
        template.sendBodyAndProperty("test", "token", "bad");
    }

    @Override
    protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            public void configure() {

                from("direct:route1")
                        .errorHandler(defaultErrorHandler().maximumRedeliveries(2))
                        .to("direct:route2");

                Predicate got401 = exchangeProperty("CamelExceptionCaught").method("getStatusCode").isEqualTo(401);

                from("direct:route2")
                        .errorHandler(noErrorHandler())
                        .onException(HttpOperationFailedException.class).onWhen(got401).process(e -> {
                            System.out.println("resetting token");
                            e.setProperty("token", "good");}
                            ).end()
                        .choice()
                            .when()
                                .exchange(e -> e.getProperty("token").equals("bad"))
                                .throwException(new HttpOperationFailedException("https://urldefense.com/v3/__http://test.com__;!!LdWlNaMnLCM!LWsFvGv33bA3AwlBzKAGVCRo3v1X9V-34fscqIrCuX26H_OWbJ9mfLc8YCLRbabA0XaZ$ ", 401, "not authenticated", "/doIt", new HashMap<>(), "bad token"))
                            .otherwise()
                                .log("token is good");
            }
        };
    }
}

Cheers,
Dmitry
Reply | Threaded
Open this post in threaded view
|

RE: errorHandler + onException

dimas
Made it to work by changing the configure() to:
   
protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            public void configure() {

                Predicate got401 = exchangeProperty("CamelExceptionCaught").method("getStatusCode").isEqualTo(401);

                from("direct:route1")
                        .errorHandler(defaultErrorHandler().maximumRedeliveries(2))
                        .to("direct:route2");

                from("direct:route2")
                        .errorHandler(noErrorHandler())
                        .log("starting route...")
                        .choice()
                            .when()
                                .exchange(e -> e.getProperty("token").equals("bad"))
                                .doTry()
                                    .throwException(new HttpOperationFailedException("http://test.com", 401, "not authenticated", "/doIt", new HashMap<>(), "bad token"))
                                .doCatch(HttpOperationFailedException.class).onWhen(got401).process(e -> {
                                    System.out.println("resetting token");
                                    e.setProperty("token", "good");
                                    throw new RuntimeException("this is to trigger re-delivery of the route1");
                                }).endDoTry()
                        .endChoice()
                        .otherwise()
                                .log("token is good");
            }
        };
    }

Note, I'm throwing exception in order to trigger the redelivery with updated token -  not ideal. Is this can be achieved somehow else?

Also, for some reason I'm seeing following logs:

12:41:17.149 [main] INFO  route6 - starting route...
12:41:18.154 [main] INFO  route6 - starting route...
resetting token
12:41:19.154 [main] INFO  route6 - starting route...
12:41:19.154 [main] INFO  route6 - token is good

I.e. route2 is started twice before getting into the doCatch() code. Im curious why this is happening?
 

Cheers,
Dmitry


-----Original Message-----
From: Shultz, Dmitry
Sent: Wednesday, May 27, 2020 3:26 PM
To: [hidden email]
Subject: RE: errorHandler + onException

Sorry, there is some typo te defaultEndpoint should be the top level route : template.setDefaultEndpointUri("direct:route1");

-----Original Message-----
From: Shultz, Dmitry [mailto:[hidden email]]
Sent: Wednesday, May 27, 2020 3:04 PM
To: [hidden email]
Subject: errorHandler + onException

Hi All,

What is the best way to handle the situation when there is a need to automatically adjust  the exchange as part of the error handling and proceed with retry?

For example, there is a route1 that invokes route2 with the 'token' property set. When, during the route2 execution  there is  a failure (401 http error) I want to reset the token property value and make route1 to do the retry (with the updated property).
Here is the sample route that doesn't work (onException never called):

public class ErrorHandlingTest extends CamelTestSupport {

    @Test
    public void runIt() throws Exception {
        template.setDefaultEndpointUri("direct:route2");
        template.sendBodyAndProperty("test", "token", "bad");
    }

    @Override
    protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            public void configure() {

                from("direct:route1")
                        .errorHandler(defaultErrorHandler().maximumRedeliveries(2))
                        .to("direct:route2");

                Predicate got401 = exchangeProperty("CamelExceptionCaught").method("getStatusCode").isEqualTo(401);

                from("direct:route2")
                        .errorHandler(noErrorHandler())
                        .onException(HttpOperationFailedException.class).onWhen(got401).process(e -> {
                            System.out.println("resetting token");
                            e.setProperty("token", "good");}
                            ).end()
                        .choice()
                            .when()
                                .exchange(e -> e.getProperty("token").equals("bad"))
                                .throwException(new HttpOperationFailedException("https://urldefense.com/v3/__http://test.com__;!!LdWlNaMnLCM!LWsFvGv33bA3AwlBzKAGVCRo3v1X9V-34fscqIrCuX26H_OWbJ9mfLc8YCLRbabA0XaZ$ ", 401, "not authenticated", "/doIt", new HashMap<>(), "bad token"))
                            .otherwise()
                                .log("token is good");
            }
        };
    }
}

Cheers,
Dmitry