2

I have successfully created few routes overriding configure() method of RouteBuilder. A for loop is used to generate routes on application startup, for eg:

Route1: from("direct:Route1").to("netty-http:http://localhost:8080/route1)

Route2: from("direct:Route2").to("netty-http:http://localhost:8081/route2)

Route3: from("direct:Route3").to("netty-http:http://localhost:8082/route3)

Route4: from("direct:Route4").to("netty-http:http://localhost:8083/route4)

Route5: from("direct:Route5").to("netty-http:http://localhost:8084/route5)

for (endpoint in endpoints.iterator()) {

        from("direct:" + endpoint.getEndpointRouteName())
                .process(getProcessor(endpoint.getEndpointProcessor(), endpoint.getEndpointRouteName(), objectMapper))
                .setHeader(Exchange.HTTP_METHOD, simple(endpoint.getEndpointRequestMethod()))
                .setHeader(Exchange.CONTENT_TYPE, constant(endpoint.getEndpointContentType()))
                .to("netty-http:" + endpoint.getEndpointUrl())
    }


private fun getProcessor(processorClassName: String, name: String, objectMapper: ObjectMapper): Processor {
    var processorClass = Class.forName("com.demo.camelpoc.processors.$name.$processorClassName")

    return processorClass.getDeclaredConstructor(ObjectMapper::class.java).newInstance(objectMapper) as Processor
}

And there is a source endpoint which starts the workflow. For example the default workflow generated in runtime:

// Workflow
    from("netty-http:$sourceUrl").process {
        it.setProperty("Workflow", workflowMap)
    }
            .dynamicRouter(bean(DynamicRouteBean::class.java, "route(*, *, ${startEndpoint})"))

where workflowMap (Used in DynamicRouteBean) is a map of endpoint strings like Key: "direct:Route1 " Value : "direct:Route2", Key: "direct:Route2 " Value : "direct:Route3"... etc

Requirement: Retry sending to the same endpoint in the workflow when exception is thrown in that particular route

For eg:

Lets say, an exception occurs at direct:Route2, I want to retry sending to direct:Route2.

Here is my DynamicRouteBean class.

class DynamicRouteBean {

    fun route(
        @Header(Exchange.SLIP_ENDPOINT) previousRoute: String?,
        exchange: Exchange,
        startEndpoint: String
    ): String? {

         if(checkException(exchange)) {
             return exchange.getProperty(Exchange.SLIP_ENDPOINT) as String
         }

        if (exchange.getProperty(Properties.STOP_ROUTE) != null && exchange.getProperty(Properties.STOP_ROUTE) == true) {
            return null
        }
        val workflow: MutableMap<String, Pair<String, String?>> =
            exchange.getProperty("Workflow") as MutableMap<String, Pair<String, String?>>

        return when (previousRoute) {
            null ->
                startEndpoint
            else -> {
                val message = exchange.getIn(NettyHttpMessage::class.java)

                // Signifies last endpoint and thus means end of the route
                if (!workflow.containsKey(previousRoute)) {
                    return null
                }

                if (message?.getHeader(previousRoute.substring(9)) != null) {

                    val isSuccess = message.getHeader(previousRoute.substring(9)) == true
                    if (isSuccess) {
                        "${workflow[previousRoute]?.first}"
                    } else if (workflow[previousRoute]?.second != null) {
                        "${workflow[previousRoute]?.second}"
                    } else {
                        null
                    }
                } else {
                    null
                }
            }
        }
    }

When I return current Exchange.SLIP_ENDPOINT property as String on exception, it doesn't call that endpoint again but exception message is returned back to the consumer.

Whereas it works in normal cases when there is no exception. Suggestions would be very helpful on handling this scenario.

  • Took a different way to fix the above issue, making use of onException(Exception::class).onWhen(some condition).continued(true) . However, it does not call that route again, but continues. Earlier, thought of doing that in Dynamic router itself, as according to my use case had to modify the exchange body before calling the same route again. – Shashanka Kalita Jun 25 '21 at 05:41

0 Answers0