Reputation: 850
I am using Apache Camel to implement Rest APIs. I've 2 RouteBuilder
types defining all the Camel routes, my application needs. All REST endpoints reside in RestRouter
, and it frames the execution using CustomRouter
. For example, I've RestRouter
to hold my REST routes
public class RestRouter extends RouteBuilder
{
@Override
public void configure() throws Exception
{
rest("/sample")
.post()
.route()
.routeId("postSample")
.to("direct:validate")
.to("direct:save")
.endRest();
}
}
And another RouteBuilder called CustomRouter
to bundle non-REST routes.
public class CustomRouter extends RouteBuilder
{
@Override
public void configure() throws Exception
{
onException(ValidationException.class)
.handled(true)
.setBody(simple("${exchangeProperty[CamelExceptionCaught]}"))
.to("bean:exceptionHandler?method=constraintViolationHandler")
.setHeader(Exchange.CONTENT_TYPE, constant(ErrorResponse.class.getName()))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(HttpStatus.SC_BAD_REQUEST));
validator()
.type(Sample.class)
.withBean("sampleValidator");
from("direct:validate")
.to("bean-validator://x"); // Runs javax/Hibernate annotated validations
from("direct:save")
.routeId("saveSample")
.inputTypeWithValidate(Sample.class)
.to("bean:sampleRepository?method=save");
}
}
Validation bean SampleValidator
is a Camel org.apache.camel.spi.Validator
which throws org.apache.camel.ValidationException
for any violations.
Problem with setup is that Camel doesn't invoke my custom exception handler for ValidationException
. Validation exception occurs for route saveSample. Here's my finding on how it goes further inside Camel processor types.
RedeliveryErrorHandler's handleException()
where it looks for the exception policy. Root of failing exchange (i.e. RestRouter
-> postSample) is expected here to define the exception handler.UnitOfWork
(i.e. to saveSample) to identify the exception handler.That means, for below expression, routeId is from CustomRouter and exceptionPolicy is from the RestRouter. Combination never exists and Camel fails to find the exception processor.
processor = exceptionPolicy.getErrorHandler(routeId)
In above context, I've following questions
RouterBuilder
types?UnitOfWork
to resolve the exception policy?RouteBuilder
types?Edit
I can't move to have a single RouterBuilder
.
Transformer
. This arrangement doesn't fit with how Camel invokes the Validator
(seeContractAdvice
). ContractAdvice is a CamelInternalProcessorAdvice
which applies Transformer
(if intype != outtype) and Validator
.RouterBuilder
will need me to move Avro-to-Entity logic to a Camel Transformer
, and that approach would differ greatly with the way we're doing currently. But yes, single RouterBuilder + Transformer + Validator should work.Upvotes: 1
Views: 6926
Reputation: 3665
See if it works when you have all the routes in a single RouteBuilder
. "Global" exception handlers such as yours are not really global as they are applied to all routes built by that specific builder, so I wouldn't expect your onException
to be applied to the REST route.
Alternatively move the onException
in to the REST builder. The handler sets HTTP status codes, so on the surface looks like it would be better packaged with REST routes.
Upvotes: 0
Reputation: 1948
Have a look at this example from Camel In Action which demonstrates how to reuse the error-handling across route builders defined in Java DSL.
BaseRouteBuilder and InboxRouteBuilder and OrderRouteBuilder
You can create a base class where you setup the context-scoped error configuration.Then your RouteBuilder classes are extending this base class and calling calling super.configure to get the common configuration.
Upvotes: 1