'How to stop camel doWhile loop
We have a independent bundle creating factory parts based on a few header variables [direct-vm:createPartService].
My application needs loop through a list of parts and call this bundle repetitively. My partBean.update method just retrieve part info from a part list, setup the header variables and then invoke the createPartService.
I uses the following doWhile loop. I find when createPartService return status is ERROR, the following loop works perfectly. The workflow exits from the loop and goes to exception handling section. But, when the createPartService return status never error, i.e., every createPartService is SUCCESS, the while loop never stop.
<loop doWhile="true">
<simple>${header.STATUS} == 'SUCCESS'</simple>
<bean ref="partBean" method="update"/>
<to uri="direct-vm:createPartService"/>
<choice>
<when>
<simple>${header.STATUS} == 'ERROR'</simple>
<throwException exceptionType="java.lang.Exception message="${header.ERROR_MESSAGE}"/>
<to uri="mock:endPartsError"/>
</when>
<otherwise>
<log message="### update part succeeded" loggingLevel="DEBUG"/>
</otherwise>
</choice>
</loop>
Then, I tried and another condition,
<simple>${header.STATUS} == 'SUCCESS' && ${exchangeProperty[CamelLoopIndex]} < ${headers.PART_COUNT}</simple>
Camel seems does not accept logic 'and'. The above evaluation always returns false. I also tried replace '&&' with 'and', or the corresponding html entity. There is no difference. Any suggestion on looping through a list and exit gracefully when there is no error?
Solution 1:[1]
You did not set your loop terminate condition properly.
Use a bean to control your looping terminate condition
Camel Spring XML
<loop doWhile="true">
<simple resultType="java.lang.Boolean">${bean:partBean?method=isContinueLoop}</simple>
... do stuff here ...
</loop>
Java Bean
public Boolean isContinueLoop(Exchange exchange) throws Exception {
// System.out.println("LoopIndex: " + exchange.getProperty(Exchange.LOOP_INDEX));
Boolean result = false;
String status = exchange.getIn().getHeader("STATUS", String.class);
Integer loopIndex = exchange.getProperty(Exchange.LOOP_INDEX, -1, Integer.class);
int maxSize = exchange.getIn().getHeader("PART_COUNT", Integer.class);
if (status != null && status.equals("SUCCESS") && loopIndex < maxSize) {
result = Boolean.TRUE;
}
return result;
}
The main problem to the condition ${header.STATUS} == 'SUCCESS' && ${exchangeProperty[CamelLoopIndex]} < ${headers.PART_COUNT}
is not on the AND operator, but the value of ${exchangeProperty[CamelLoopIndex]}
.
If you uncomment the system print in the java bean, you could observe the CamelLoopIndex's value is change as : null -> 0 -> 1 -> 2 -> ..., the null value is the root problem to make your condition return false. To avoid this in Camel Spring XML Simple language, you need a null check on CamelLoopIndex with a OR operator.
In this sense, you will need both a AND operator and a OR operator. However, this is unsupported by simple language currently as state in Simple language page Section 'Using and / or'.
Solution 2:[2]
<split>
offers an excellent solution for my use case. In the following code sample, the findParts method returns a list of Part object. The update method setups header variables needed for web service call (createPartService).
<route id="WebServiceUpdateParts">
<from uri="direct:updateParts"/>
<split stopOnException="true">
<method ref="partBean" method="findParts"/>
<bean ref="partBean" method="update"/>
<to uri="direct-vm:createPartService"/>
</split>
<to uri="mock:endUpdateParts"/>
</route>
Solution 3:[3]
If you wanna stop the loop after specific round, you can use this:
from("direct:test").setProperty("CamelLoopIndex",constant(0)).loopDoWhile(simple("${exchangeProperty.CamelLoopIndex} <= 3")).log("=====${exchangeProperty.CamelLoopIndex}");
Notice that you must declare CamelLoopIndex property explicitly before the loop, otherwise Camel will not understand the contiditon when starts up the route, because CamelLoopIndex property is created after the loop begins.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | hk6279 |
Solution 2 | Chris W |
Solution 3 |