Reputation: 341
I have a Route like the following.
SimpleScheduledRoutePolicy policy = new SimpleScheduledRoutePolicy();
policy.setRouteStartDate(new Date());
policy.setRouteStartRepeatInterval(1000);
from("file:data/in")
.routePolicy(policy)
.to("direct:validateInput")
.to("direct:changeInput")
.to("file:data/out");
So the Route takes an file from the inputfolder every second. After some validation and changing it writes it out to an out folder.
Now I would like to be able to close the actual route at every point. So If some error happens at the direct route validateInput the following two parts should not be excecuted.
I could do this with some doTry() and doCatch() but this will look ugly and hard to read.
Question: is it somehow possible to stop on loop of the main route without stopping the route complete? Like this the actual file won't be printed to the outfolder but the file comming in 5 seconds can be processed in normal way.
Creating a new Process and stopping the main Route in a seperate Thread doesn't work.
The file is still written into the date/out folder
The route is stopped complet and won't take any files anymore.
Upvotes: 1
Views: 1306
Reputation: 341
found an answer which is good. For all folks who find this question here an "complete" solution.
public void start() {
try {
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
errorHandler(loggingErrorHandler().level(LoggingLevel.ERROR));
SimpleScheduledRoutePolicy policy = new SimpleScheduledRoutePolicy();
policy.setRouteStartDate(new Date());
policy.setRouteStartRepeatInterval(1000);
//Exception Handling in case the xsd validation fails
onException(SomeSpecialException.class)
.log(LoggingLevel.ERROR, "${exception}")
.handled(true).useOriginalMessage()
.to("file:test-data/error?autoCreate=true")
.end();
//start main route
from("file:test-data/in?delete=true")
.routePolicy(policy)
.log(LoggingLevel.DEBUG, "Processing file ${file:name}")
.to("direct:validateInput")
.to("direct:validateContent")
.to("direct:validateOutput")
.to("file:test-data/out");
//start of separate Routes
from("direct:validateInput")
.doTry()
.to("validator:message.xsd")
.doCatch(ValidationException.class)
.process(getErrorProcess());
//...
}
});
camelContext.start();
} catch (Exception e) {
LOGGER.error("Error while processing camel route: " + e.getMessage());
}
}
/**
* throws an SomeSpecialException in case of calling
*
* @return a Processor which is supposed to be called in case an {@link org.apache.camel.ValidationException} happens
*/
private Processor getErrorProcess() {
return new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
StringBuilder message = new StringBuilder();
String fileContent = exchange.getIn().getBody(String.class);
String originalErrorMessage;
try {
SchemaValidationException schemaValidationException = (SchemaValidationException) exchange.getProperties().get("CamelExceptionCaught");
originalErrorMessage = schemaValidationException.getMessage();
} catch (Exception e) {
originalErrorMessage = "Could not retrieve original error message.";
}
message.append("Could not validate import against the xsd. ")
.append("Original message: ").append(originalErrorMessage).append("; ")
.append("File:").append(fileContent);
throw new SomeSpecialException(message.toString());
}
};
}
Thanks for everyone that helped me.
Upvotes: 0
Reputation: 341
It works good, but 1 Problem is still left. My actual Example looks like the following:
SimpleScheduledRoutePolicy policy = new SimpleScheduledRoutePolicy();
policy.setRouteStartDate(new Date());
policy.setRouteStartRepeatInterval(1000);
//start main route
from("file:test-data/in?delete=true")
.routePolicy(policy)
.onException(Exception.class)
.log(LoggingLevel.ERROR, "${exception}")
.handled(true).useOriginalMessage()
.to("file://test-data/error?autoCreate=true")
.end()
.log(LoggingLevel.DEBUG, "Processing file ${file:name}")
.to("direct:validateInput")
.to("direct:validateContent")
.to("direct:validateOutput")
.to("file:test-data/out");
from("direct:validateInput")
.doTry()
.to("validator:message.xsd")
.doCatch(ValidationException.class)
.process(getErrorProcessor("Could not validate import against the xsd. Message: ${exception}; File: ${body}"));
//...
}
}
private Processor getErrorProcessor(final String message) {
return new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
throw new Exception(message);
}
};
}
If I put an incorrect file into the in folder I get the following error message:
ERROR route1:145 - java.lang.Exception: Could not validate import against the xsd. Message: ${exception}; File: ${body}
As you can see, camel replaced the ${...} attribute one time. But after this I won't replace the new ${...} elements. Any Idear how I can tell camel replace any new {...} parts or how I can replace them before by my self?
Upvotes: 0
Reputation: 21005
just have your validateInput
step throw an Exception and use an onException() clause to handle the exception, that will short-circuit the flow for just that message and allow for processing future files dropped into the 'data/in' directory normally
Upvotes: 1
Reputation: 134
I believe you best option is using doCatch and doFinally. I think anything different would be much more difficult to read and very ugly.
http://camel.apache.org/validation.html
This is the most logical approach to solving this problem.
Upvotes: 0