Run camel direct route until data processed in DB - apache-camel

I have to implement a camel route to run a specific time period. First route to check if there is any record in table. If there is record in the table then run another route to process all records.
from("quartz://Timer?cron=0+0/5+20-22+?+*+*")
.autoStartup(true)
.routeId("my-route")
.setBody(constant(sql query))
.to("jdbc:dataSource?resetAutoCommit=false")
.choice().when(header("CamelJdbcRowCount").isGreaterThan(0))
.split(body())
.setHeader("createdDate", simple("${body['CREATED']}"))
.inOut("vm:process")
.end();
from("vm:process")
.autoStartup(false)
.routeId("processrecords")
.setBody(constant("get all repords query"))
.to("jdbc:dataSource?readSize=300&useHeadersAsParameters=true&resetAutoCommit=false")
.split(body())
.setHeader("Id",simple("${body['ID']}"))
//do some thing here.
.setBody(constant("update here onc it is processed."))
.to("jdbc:dataSource?useHeadersAsParameters=true&resetAutoCommit=false");
}
vm:process route should trigger from another route 'my route'. How to run the vm:process route until all the records are processed in the database?

Related

Camel - How to stop camel route using java dsl, when using TIMER component to pool database?

I am trying to stop camel route when there is no more data in the database to pool, but unable to stop.
from("timer://pollTheDatabase?delay=50s")
.routeId("db-pooling-route")
.to("mybatis:queryToSelectData?statementType=SelectOne")
.choice()
.when().simple("${in.header.CamelMyBatisResult} == ''").stop()
.otherwise().to("direct:processing-data")
.end()
.end()
.end();
stop() means stop routing the current message, not the route itself. To stop/start routes etc you can use the controlbus component.
https://camel.apache.org/components/latest/controlbus-component.html
And since you want to stop the route from itself, then set the option async=true on the controlbus endpoint.
I tried using control-bus and it worked.
from("timer://pollTheDatabase?delay=50s&synchronous=false")
.routeId("db-pooling-route")
.to("mybatis:queryToSelectData?statementType=SelectOne")
.choice()
.when().simple("${in.header.CamelMyBatisResult} == ''")
.to("controlbus:route?async=true&routeId=db-pooling-route&action=stop")
.end()
.to("direct:processing-data");

Camel JPA component route is not executing fully

I have created a simple route using JPA component
`fromF("jpa:%s?consumer.namedQuery=step1&delay=5s&consumeDelete=false&consumeLockEntity=false", Event.class.getName())
.log("Query Fired")
.process(exchange -> System.out.println(exchange.getIn().getBody()))
.end();
in console I can see the query being fired
Hibernate: select event0_.eventId as eventId1_3_, event0_.event_desc as event_desc2_3_, event0_.event_name as event_name3_3_, event0_.event_type as event_type4_3_, event0_.valid_from_date as valid_from_date5_3_, event0_.insight as insight6_3_, event0_.is_processed as is_processed7_3_, event0_.severity as severity8_3_, event0_.source_system_name as source_system_name9_3_, event0_.valid_to_date as valid_to_date10_3_ from OV90PLFM.event event0_ where event0_.is_processed=0
but after this I cannot see log getting printed and the processor is also not getting executed.
after a delay a query continues to get fire but no exception is there and route processing is not completed. the log is not printing and the processor is also not getting called.
I have changed the log level still exception is not there.
I just want my route to complete its execution so i can write some thing in processor.
same query gives all the rows in database.
Please suggest what is going wrong?

Apache Camel aggregator with parallelProcessing completion callback

I'm using Apache Camel aggregator with parallelProcessing to process aggregated exchanges concurrently:
from("direct:test")
.aggregate(constant(true), new GroupedMessageAggregationStrategy())
.completionSize(10)
.completionTimeout(3000)
.parallelProcessing()
.to("direct:test2")
.log("Completed!") //executed for each aggregated exchange
.end();
What I need is to get a callback when all aggregated exchanges are processed and log "Completed!" after that.
Currently, (see the log statement above) - it's getting executed for each aggregated exchange.
Thanks in advance for any suggestion.
Maybe you need to log "Completed!" in different route. Someting like this:
from("direct:start")
.split(body())
.to("direct:test")
.end()
.log("Completed!");
from("direct:test")
.aggregate(constant(true), new GroupedMessageAggregationStrategy())
.completionSize(10)
.completionTimeout(3000)
.parallelProcessing()
.to("direct:test2");
from("direct:test2")
.log("do something");

Handle exception from load balancer only once (when failover is exhausted)

My code consumes jms queue and through lb redirects to external http client.
I need to log original message for every failed delivery to local directory.
Problem is that onException is caught by each failover.
Is there any way how to achieve this?
Pseudo code:
onException(Exception.class).useOriginalMessage()
.setHeader(...)
.to("file...")
.setHeader(...)
.to("file...")
from("activemq...")
.process(...)
.loadBalance().failover(...)
.to("lb-route1")
.to("lb-route2")
.end()
.process()
.to("file...")
from("lb-route1")
.recipientList("dynamic url")
.end()
from("lb-route2")
.recipientList("dynamic url")
.end()
I have not tested this logic with multiple to statements, but when I have my list of endpoints in an array this logic functions just fine. I will attempt to deliver to the first endpoint, if I cannot I will attempt to deliver this to the second endpoint. If an exception occurs at the second endpoint it will propagate back to the route's error handler. If you need it to round robin instead, change the last false on the failover statement to a true.
String[] endpointList = {"direct:end1", "direct:end2"};
from("direct:start")
.loadbalance().failover(endpointList.length-1, false, false)
.to(endpointList);

Camel Redirecting to another route on throttling

I have a camel route which will be throttled on recieving loads of messages. Suppose the maximum exchanges i defined is 3 per 2 seconds and the route recieves more than the limit i want to redirect those messages to some other load balancer route. Can someone help me how to achieve it??
If I am understanding your question right you want to throttle your incoming messages then loadbalance those messages out to a different route or system.
from("SomethingSendingMeMessages")
.throttle(3)
.loadbalance().roundRobin()
.to("place1", "place2", "place3")
.end();
If you need to have the throttling route send to a second route that contains the loadbalancer you can do it like follows:
from("SomethingSendingMeMessages")
.throttle(3)
.to("direct:mySecondRoute");
from("direct:mySecondRoute")
.loadbalance().roundRobin()
.to("place1", "place2", "place3")
.end();
Another option you could explore is throttling after the loadbalancer to control each individual route's method.
from("SomethingSendingMeMessages")
.loadbalance().roundRobin()
.to("direct:place1", "direct:place2")
.end();
from("direct:place1")
.throttle(3)
.to("myOtherWork");
from("direct:place2")
.throttle(3)
.to("myOtherWork");

Resources