Add a DataFormat programatically
I'm having trouble adding the ProtobufDataFormat to a route. I have ActiveMQ BytesMessages whose bodies are Protobuf messages. The documentation (http://camel.apache.org/protobuf.html) certainly looks straightforward, so here's what I have: ProtobufDataFormat protobufFormat = new ProtobufDataFormat(); context.addRoutes(new RouteBuilder() { public void configure() throws Exception { from("jms:queue:test) .unmarshal(protobufFormat) .process((exchange) -> {...}); But this gives me an exception: Caused by: java.lang.IllegalArgumentException: Data format 'protobuf' could not be created. Ensure that the data format is valid and the associated Camel component is present on the classpath at org.apache.camel.model.DataFormatDefinition.getDataFormat(DataFormatDefinition.java:107) at org.apache.camel.model.DataFormatDefinition.getDataFormat(DataFormatDefinition.java:88) at org.apache.camel.model.MarshalDefinition.createProcessor(MarshalDefinition.java:177) at org.apache.camel.model.ProcessorDefinition.makeProcessorImpl(ProcessorDefinition.java:545) at org.apache.camel.model.ProcessorDefinition.makeProcessor(ProcessorDefinition.java:506) at org.apache.camel.model.ProcessorDefinition.addRoutes(ProcessorDefinition.java:222) at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:1068) ... 42 more Any ideas? Also, is there a way to programatically add the ProtobufDataDefinition to the CamelContext when I create it so I can use it in routes without instantiating it? (I tried adding it as a serivce, registering it in the registry, and adding it to the context's data format map, and I always got the same exception as the one above.)
Handling errors
I'm having trouble understanding how to write and use an error handler. The use case is testing a custom Camel component. I would like to have an error handler that just collects any exceptions thrown by the endpoint's producer. I somewhat naively assumed this would be simple. I thought the Camel framework must catch any exception, add it the exchange, and invoke the handler's process method. That appears not to be the case. Below is my attempt. The test is set up so my the producer will throw an exception. To my surprise, the CaptureErrorHandler.process method is being invoked twice. my component's producer is never invoked. But If I remove usage of my my error handler from the RouteBuilder, the producer is invoked, and it throws an exception that is logged by the DefaultErrorHandler. Clearly, I don't understand how error handles are supposed to be used. Can someone enlighten me, or point me to more detailed documentation? The Camel documentation for ErrorHandler is pretty light on details. Alternatively, maybe there's a simpler approach I can take for testing my component. The RouteBuilder's configure method looks like this: public void configure() throws Exception { errorHandler(new CaptureErrorHandlerBuilder()); from(destinations) .process(new Counter()) .to("foo:endpoint"); } And the CaptureErrorHandlerBuilder and CaptureErrorHandler looks like this: private class CaptureErrorHandlerBuilder extends ErrorHandlerBuilderSupport { @Override public boolean supportTransacted() { return false; } @Override public ErrorHandlerBuilder cloneBuilder() { return new CaptureErrorHandlerBuilder(); } @Override public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception { CaptureErrorHandler handler = new CaptureErrorHandler(); configure(routeContext, handler); return handler; } } private class CaptureErrorHandler implements ErrorHandler { @Override public void process(Exchange exchange) throws Exception { Exception e = exchange.getException(); // For now, just log the exception if (e != null) { e.printStackTrace(); } } }
Re: Handling errors
Well, of course I read that, but all I want is access to the actual Exception objects in my test. I can add the try/catch clauses, but as nearly as I can tell the only thing you can do with the catch is route to another endpoint. Isn't there a simple way to get at the underlying exceptions? On Tue, Jan 3, 2017 at 10:57 AM, Claus Ibsen wrote: > Hi > > You should not build your own, but use what is OOTB > http://camel.apache.org/error-handling-in-camel.html > > If you have Camel in Action book then it has a full chapter devoted to > error handling. > > > > On Tue, Jan 3, 2017 at 7:44 PM, Robert Huffman > wrote: > > I'm having trouble understanding how to write and use an error handler. > The > > use case is testing a custom Camel component. I would like to have an > error > > handler that just collects any exceptions thrown by the endpoint's > producer. > > > > I somewhat naively assumed this would be simple. I thought the Camel > > framework must catch any exception, add it the exchange, and invoke the > > handler's process method. That appears not to be the case. > > > > Below is my attempt. The test is set up so my the producer will throw an > > exception. To my surprise, the CaptureErrorHandler.process method is > being > > invoked twice. my component's producer is never invoked. > > > > But If I remove usage of my my error handler from the RouteBuilder, the > > producer is invoked, and it throws an exception that is logged by the > > DefaultErrorHandler. > > > > Clearly, I don't understand how error handles are supposed to be used. > Can > > someone enlighten me, or point me to more detailed documentation? The > Camel > > documentation for ErrorHandler is pretty light on details. Alternatively, > > maybe there's a simpler approach I can take for testing my component. > > > > > > The RouteBuilder's configure method looks like this: > > > > public void configure() throws Exception { > > errorHandler(new CaptureErrorHandlerBuilder()); > > from(destinations) > > .process(new Counter()) > > .to("foo:endpoint"); > > } > > > > > > And the CaptureErrorHandlerBuilder and CaptureErrorHandler looks like > this: > > > > private class CaptureErrorHandlerBuilder extends > ErrorHandlerBuilderSupport > > { > > > > @Override > > public boolean supportTransacted() { > > return false; > > } > > > > @Override > > public ErrorHandlerBuilder cloneBuilder() { > > return new CaptureErrorHandlerBuilder(); > > } > > > > @Override > > public Processor createErrorHandler(RouteContext routeContext, > Processor > > processor) throws Exception { > > CaptureErrorHandler handler = new CaptureErrorHandler(); > > configure(routeContext, handler); > > return handler; > > } > > } > > > > private class CaptureErrorHandler implements ErrorHandler { > > @Override > > public void process(Exchange exchange) throws Exception { > > Exception e = exchange.getException(); > > > > // For now, just log the exception > > > > if (e != null) { > > e.printStackTrace(); > > > > } > > > > } > > } > > > > -- > Claus Ibsen > - > http://davsclaus.com @davsclaus > Camel in Action 2: https://www.manning.com/ibsen2 >
Re: Handling errors
Ah, nice. I did not see that. Thanks for pointing it out. (And I'll check out that chapter, too.) On Tue, Jan 3, 2017 at 1:15 PM, Claus Ibsen wrote: > Hi > > There is this FAQ > http://camel.apache.org/why-is-the-exception-null-when-i- > use-onexception.html > > On Tue, Jan 3, 2017 at 9:31 PM, Robert Huffman > wrote: > > Well, of course I read that, but all I want is access to the actual > > Exception objects in my test. I can add the try/catch clauses, but as > > nearly as I can tell the only thing you can do with the catch is route to > > another endpoint. Isn't there a simple way to get at the underlying > > exceptions? > > > > > > On Tue, Jan 3, 2017 at 10:57 AM, Claus Ibsen > wrote: > > > >> Hi > >> > >> You should not build your own, but use what is OOTB > >> http://camel.apache.org/error-handling-in-camel.html > >> > >> If you have Camel in Action book then it has a full chapter devoted to > >> error handling. > >> > >> > >> > >> On Tue, Jan 3, 2017 at 7:44 PM, Robert Huffman < > robert.huff...@gmail.com> > >> wrote: > >> > I'm having trouble understanding how to write and use an error > handler. > >> The > >> > use case is testing a custom Camel component. I would like to have an > >> error > >> > handler that just collects any exceptions thrown by the endpoint's > >> producer. > >> > > >> > I somewhat naively assumed this would be simple. I thought the Camel > >> > framework must catch any exception, add it the exchange, and invoke > the > >> > handler's process method. That appears not to be the case. > >> > > >> > Below is my attempt. The test is set up so my the producer will throw > an > >> > exception. To my surprise, the CaptureErrorHandler.process method is > >> being > >> > invoked twice. my component's producer is never invoked. > >> > > >> > But If I remove usage of my my error handler from the RouteBuilder, > the > >> > producer is invoked, and it throws an exception that is logged by the > >> > DefaultErrorHandler. > >> > > >> > Clearly, I don't understand how error handles are supposed to be used. > >> Can > >> > someone enlighten me, or point me to more detailed documentation? The > >> Camel > >> > documentation for ErrorHandler is pretty light on details. > Alternatively, > >> > maybe there's a simpler approach I can take for testing my component. > >> > > >> > > >> > The RouteBuilder's configure method looks like this: > >> > > >> > public void configure() throws Exception { > >> > errorHandler(new CaptureErrorHandlerBuilder()); > >> > from(destinations) > >> > .process(new Counter()) > >> > .to("foo:endpoint"); > >> > } > >> > > >> > > >> > And the CaptureErrorHandlerBuilder and CaptureErrorHandler looks like > >> this: > >> > > >> > private class CaptureErrorHandlerBuilder extends > >> ErrorHandlerBuilderSupport > >> > { > >> > > >> > @Override > >> > public boolean supportTransacted() { > >> > return false; > >> > } > >> > > >> > @Override > >> > public ErrorHandlerBuilder cloneBuilder() { > >> > return new CaptureErrorHandlerBuilder(); > >> > } > >> > > >> > @Override > >> > public Processor createErrorHandler(RouteContext routeContext, > >> Processor > >> > processor) throws Exception { > >> > CaptureErrorHandler handler = new CaptureErrorHandler(); > >> > configure(routeContext, handler); > >> > return handler; > >> > } > >> > } > >> > > >> > private class CaptureErrorHandler implements ErrorHandler { > >> > @Override > >> > public void process(Exchange exchange) throws Exception { > >> > Exception e = exchange.getException(); > >> > > >> > // For now, just log the exception > >> > > >> > if (e != null) { > >> > e.printStackTrace(); > >> > > >> > } > >> > > >> > } > >> > } > >> > >> > >> > >> -- > >> Claus Ibsen > >> - > >> http://davsclaus.com @davsclaus > >> Camel in Action 2: https://www.manning.com/ibsen2 > >> > > > > -- > Claus Ibsen > - > http://davsclaus.com @davsclaus > Camel in Action 2: https://www.manning.com/ibsen2 >
Re: Handling errors
To close this discussion, Claus's solution, along with try, catch and process, clauses, worked for me. The route looks like this: from(destinations) .doTry() .to("foo:bar") .doCatch(Exception.class) .process((exchange) -> handleException(exchange)); And the method to add the exception to a collection looks like this: private void handleException(Exchange exchange) { Exception e = exchange.getException(); if (e == null) { // If another handler marked the exception as handled, we have to get the // original exception from a property. // See http://camel.apache.org/why-is-the-exception-null-when-i-use-onexception.html e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); } if (e != null) { exceptions.add(e); } } Thanks for the help. On Tue, Jan 3, 2017 at 2:31 PM, Robert Huffman wrote: > Ah, nice. I did not see that. Thanks for pointing it out. (And I'll check > out that chapter, too.) > > > On Tue, Jan 3, 2017 at 1:15 PM, Claus Ibsen wrote: > >> Hi >> >> There is this FAQ >> http://camel.apache.org/why-is-the-exception-null-when-i-use >> -onexception.html >> >> On Tue, Jan 3, 2017 at 9:31 PM, Robert Huffman >> wrote: >> > Well, of course I read that, but all I want is access to the actual >> > Exception objects in my test. I can add the try/catch clauses, but as >> > nearly as I can tell the only thing you can do with the catch is route >> to >> > another endpoint. Isn't there a simple way to get at the underlying >> > exceptions? >> > >> > >> > On Tue, Jan 3, 2017 at 10:57 AM, Claus Ibsen >> wrote: >> > >> >> Hi >> >> >> >> You should not build your own, but use what is OOTB >> >> http://camel.apache.org/error-handling-in-camel.html >> >> >> >> If you have Camel in Action book then it has a full chapter devoted to >> >> error handling. >> >> >> >> >> >> >> >> On Tue, Jan 3, 2017 at 7:44 PM, Robert Huffman < >> robert.huff...@gmail.com> >> >> wrote: >> >> > I'm having trouble understanding how to write and use an error >> handler. >> >> The >> >> > use case is testing a custom Camel component. I would like to have an >> >> error >> >> > handler that just collects any exceptions thrown by the endpoint's >> >> producer. >> >> > >> >> > I somewhat naively assumed this would be simple. I thought the Camel >> >> > framework must catch any exception, add it the exchange, and invoke >> the >> >> > handler's process method. That appears not to be the case. >> >> > >> >> > Below is my attempt. The test is set up so my the producer will >> throw an >> >> > exception. To my surprise, the CaptureErrorHandler.process method is >> >> being >> >> > invoked twice. my component's producer is never invoked. >> >> > >> >> > But If I remove usage of my my error handler from the RouteBuilder, >> the >> >> > producer is invoked, and it throws an exception that is logged by the >> >> > DefaultErrorHandler. >> >> > >> >> > Clearly, I don't understand how error handles are supposed to be >> used. >> >> Can >> >> > someone enlighten me, or point me to more detailed documentation? The >> >> Camel >> >> > documentation for ErrorHandler is pretty light on details. >> Alternatively, >> >> > maybe there's a simpler approach I can take for testing my component. >> >> > >> >> > >> >> > The RouteBuilder's configure method looks like this: >> >> > >> >> > public void configure() throws Exception { >> >> > errorHandler(new CaptureErrorHandlerBuilder()); >> >> > from(destinations) >> >> > .process(new Counter()) >> >> > .to("foo:endpoint"); >> >> > } >> >> > >> >> > >> >> > And the CaptureErrorHandlerBuilder and CaptureErrorHandler looks like >> >> this: >> >> > >> >> > private class CaptureErrorHandlerBuilder extends >> >> ErrorHandlerBuilderSupport >> >> > { >> >> > >> >> > @Override >> >> > public boolean supportTransacted() { >> >> >