Hi I have created an example how to do your own custom processor as failover. Its based on an unit test and the code is here:
https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/test/java/org/apache/camel/issues/CustomFailveOverProcessor.java The code is based on Camel 2.0, but you can do the same in Camel 1.x. On Sat, May 16, 2009 at 4:37 PM, Claus Ibsen <[email protected]> wrote: > Hi > > Sometimes its easier to read the code when there is quite a bit if you > paste it using http://pastebin.com/ or the likes. > > > > On Fri, May 15, 2009 at 5:44 PM, Nasim Anza <[email protected]> wrote: >> Thanks Claus for answers. >> >> My processor is working fine and it finds the URL to invoke but the problem >> is on the last step : the next endpoint is not called with right XML input : >> >> Just to explain my actual problem : >> Let's assume that my route is : >> >> from("direct:endpointA") >> .setHeader(HttpProducer.HTTP_URI).simple("http://myAddressA") >> .process(myFailOverProcessor("direct:endpointB")); //forward HTTP response >> to the direct:endpointB >> >> from("direct:endpointB") >> .to("log:display the XML input"); //just display it to compare XMLs >> >> The displayed XML on the "log:..." endpoint doesn't correspond to the http >> response of "http://myAddressA"... >> >> Here is my Processor class : >> >> >> public class FailOverProcessor implements Processor{ >> >> public FailOverProcessor(String endpoint) { >> this.endpoint=endpoint; >> } >> >> public void process(Exchange exchange) throws Exception { >> Exchange out = null; >> int index = 0; >> out = processExchange(exchange); >> >> while (exchange.getException() != null){ >> >> //reset the exchange exceptiuon >> exchange.setException(null); >> >> if (index++ < 4 ) { >> System.out.println(index+" : processExchange ....."); >> >> out = processExchange(exchange); >> } >> } >> >> if(endpoint != null) >> { >> ProducerTemplate<Exchange> template = >> exchange.getContext().createProducerTemplate(); >> if(out != null) >> { >> >> Message responseOut = exchange.getOut(); >> int responseCode = >> responseOut.getHeader(HttpProducer.HTTP_RESPONSE_CODE, Integer.class); >> System.out.println("\n\n Response out \\n" + responseCode + >> responseOut.getBody(String.class)); >> >> //I've tried all the these calls but no valid response >> // template.send(endpoint, exchange.getOut().getExchange()); >> // template.sendBody(endpoint, exchange.getBody()); >> template.send(endpoint, exchange); >> } >> } >> } >> >> private Exchange processExchange(Exchange exchange) { >> >> Exchange out = null; >> >> try { >> >> //Define the strategy to use for processing message >> String uri = >> exchange.getIn().getHeader(org.apache.camel.component.http.HttpProducer.HTTP_URI).toString(); >> System.out.println("Current URI ==> "+uri); >> >> //just for test >> if(uri.equalsIgnoreCase("http://myAddressA")) >> exchange.getIn().setHeader(HttpProducer.HTTP_URI, " >> http://serverA/appli1"); >> else if(uri.equalsIgnoreCase("http://myAddressB")) >> exchange.getIn().setHeader(HttpProducer.HTTP_URI, " >> http://serverB/appli2"); >> else >> exchange.getIn().setHeader(HttpProducer.HTTP_URI, " >> http://serverC/error"); >> >> ProducerTemplate<Exchange> template = >> exchange.getContext().createProducerTemplate(); >> >> out = template.send(uri, exchange); >> >> } catch (Throwable th) { >> //Set the thrown exception >> exchange.setException(th.getCause()); >> } >> >> return out; >> } >> } >> >> Thanks for your help >> Nasmo >> >> >> >> >> On Fri, May 15, 2009 at 1:00 PM, Claus Ibsen <[email protected]> wrote: >> >>> You need to test the exchange afterwards if there was an exception. >>> >>> template.send(endpoint, exchange); >>> if (exchange.getException() != null) { >>> // ops it failed so call the next URI as fallback >>> ... >>> } >>> >>> >>> >>> >>> > >>> > Unfortunately this doesn't change anything on the SMIX console. I have >>> the >>> > same error : >>> > >>> > FATAL - DeadLetterChannel - Failed delivery for exchangeId: >>> > ID-ROME/1982-1242375956166/0- >>> > Handled by the failure >>> processor:sendTo(Endpoint[direct:deadLetterChannel]) >>> > >>> > Thanks for help >>> > >>> > On Fri, May 15, 2009 at 11:10 AM, Claus Ibsen <[email protected]> >>> wrote: >>> > >>> >> Hi >>> >> >>> >> You should *not* route after your custom failover processor. You >>> >> custom failover processor should be the end of the route (eg no more >>> >> .to after your processor). >>> >> >>> >> >>> >> >>> >> On Fri, May 15, 2009 at 11:05 AM, Nasim Anza <[email protected]> >>> >> wrote: >>> >> > Hi, >>> >> > >>> >> > I’ve tried this solution: >>> >> > I started by developing a processor that loops on URIs until getting a >>> >> valid >>> >> > answer. >>> >> > The only problem is my route is interrupted at the end of the first >>> >> > processing, so no way to pass from first block (addressA) to next >>> block >>> >> > (AddressB). >>> >> > >>> >> > The process() method loops on all URI until getting the valid URI. >>> This >>> >> > works but after that I got a fatal error and the route flow was >>> >> interrupted. >>> >> > Below the error I got on ServiceMix console: >>> >> > >>> >> > ---------------- >>> >> > >>> >> > FATAL - DeadLetterChannel - Failed delivery for >>> exchangeId: >>> >> > ID-ROME/1982-1242375956166/0-4. Handled by the failure processor: >>> >> > sendTo(Endpoint[direct:deadLetterChannel]) >>> >> > 15 mai 2009 09:32:37 org.apache.cxf.phase.PhaseInterceptorChain >>> >> doIntercept >>> >> > INFO: Interceptor has thrown exception, unwinding now >>> >> > org.apache.xerces.dom.TextImpl >>> >> > >>> >> > ---------------- >>> >> > >>> >> > Here is my Camel route: >>> >> > >>> >> > * //Declare Deadletter processor* >>> >> > >>> >> > >>> >> >>> *errorHandler(deadLetterChannel("direct:letter").onRedelivery(myProcessor)); >>> >> > * >>> >> > >>> >> > * //Declare global exception* >>> >> > >>> >> > *onException(Exception.class).maximumRedeliveries(5) //5 : because I >>> have >>> >> 5 >>> >> > address maximum to call* >>> >> > >>> >> > *final Processor myprocessor() = new Processor(Exchange exchange) >>> throws >>> >> > Exception{* >>> >> > ** >>> >> > >>> >> > *ProducerTemplate<Exchange> template >>> >> > exchange.getContext().createProducerTemplate(); >>> >> > String uri = >>> >> exchange.getIn().getHeader(HttpProducer.**HTTP_URI).toString(); >>> >> > * >>> >> > >>> >> > *//This method returns the valid list depending on the current http >>> URI* >>> >> > >>> >> > *List<Strig> uris = getUriList(uri);* >>> >> > >>> >> > *for (String uri : uris) {* >>> >> > >>> >> > * try {* >>> >> > >>> >> > * template.send(uri, exchange);* >>> >> > >>> >> > * } catch (Exception e) {* >>> >> > >>> >> > * exchange.setExceptipn(e);* >>> >> > >>> >> > * }* >>> >> > >>> >> > * if (exchange.getException() == null) {* >>> >> > >>> >> > * return; >>> >> > } >>> >> > } >>> >> > }* >>> >> > >>> >> > * * >>> >> > >>> >> > *from("direct:endpointA") >>> >> > .setHeader(HttpProducer.HTTP_URI).simple("http://myAddressA") >>> >> > .process(myUrlLookerProcessor()) >>> >> > .to("direct:endPointB")* >>> >> > >>> >> > *from("direct:endpointB") >>> >> > .setHeader(HttpProducer.HTTP_URI).simple("http://myAddressB") >>> >> > .process(myUrlLookerProcessor()) >>> >> > .to("direct:endPointC")* >>> >> > >>> >> > * >>> >> > from("direct:endPointC") >>> >> > .to("xquery:response.xml");* >>> >> > >>> >> > *from("direct:letter") >>> >> > .to("log:dead_letterChannel?showHeaders=true&level=DEBUG");* >>> >> > >>> >> > >>> >> > >>> >> > Thanks in advance for help. >>> >> > >>> >> > Nasmo >>> >> > >>> >> > >>> >> > On Fri, May 15, 2009 at 9:41 AM, Claus Ibsen <[email protected]> >>> >> wrote: >>> >> > >>> >> >> Hi >>> >> >> >>> >> >> BTW You can also always just use a Processor and implement the >>> >> >> failover logic yourself as pure Java with try .. catch and use the >>> >> >> ProducerTemplate to send the exchange to the endpoint based on the >>> >> >> URI. >>> >> >> >>> >> >> Something like >>> >> >> ProducerTemplate template = // get it from CamelContext and get it >>> once >>> >> >> List<Strig> uris = ... >>> >> >> >>> >> >> for (String uri : uris) { >>> >> >> try { >>> >> >> template.send(uri, exchange); >>> >> >> } catch (Exception e) { >>> >> >> exchange.setExceptipn(e); >>> >> >> } >>> >> >> if (exchange.getException() == null) { >>> >> >> return; >>> >> >> } >>> >> >> } >>> >> >> >>> >> >> >>> >> >> On Thu, May 14, 2009 at 6:19 PM, Claus Ibsen <[email protected]> >>> >> >> wrote: >>> >> >> > On Thu, May 14, 2009 at 4:55 PM, Nasim Anza < >>> [email protected] >>> >> > >>> >> >> wrote: >>> >> >> >> Thanks Claus for your quick answer. >>> >> >> >> >>> >> >> >> I downloaded the source of camel 2.0 and I looked at the >>> >> >> >> FailOverLoadBalancer class. I think that this could answer to my >>> >> >> question. >>> >> >> >> I've tried to adapt the code to my requirement but I have some >>> >> questions >>> >> >> >> about the list of processors used in this class : >>> >> >> >> >>> >> >> >> 1. I don't know How to create or initialize the processors used >>> for >>> >> >> >> balancing user requests ? >>> >> >> >> >>> >> >> >> 2. Shall I create a camel Processor for each HTTP URL ? >>> >> >> >> >>> >> >> >> 3. Whait is the syntaxe (maybe something like new >>> >> Processor(myHttpURL)) >>> >> >> > Hi >>> >> >> > >>> >> >> > Yeah there is no nice DSL support for it and the loadbalance() DSL >>> >> >> > does not have a nice support for custom load balancer. >>> >> >> > So that is something we might need to improve in the future. I have >>> to >>> >> >> > remember this thread. >>> >> >> > >>> >> >> > So what you basically have to do is to add your custom load >>> balancer >>> >> >> > as a processor, so use the process() DSL. >>> >> >> > >>> >> >> > And your custom fail over loadbalancer can accept a list of >>> endpoints >>> >> >> > to select among. You can wrap an endpoint to a processor >>> >> >> > with the SendToProcessor. >>> >> >> > >>> >> >> > Something like this >>> >> >> > >>> >> >> > MyFailover my = new MyFailoverProcessor()l; >>> >> >> > my.addEndpoint("foo"); >>> >> >> > my.addEndpoint("bar"); >>> >> >> > >>> >> >> > >>> >> >> > And in the route DSL you just route to your processor >>> >> >> > from(x).process(my); >>> >> >> > >>> >> >> > And in the addEndpoint method you add the endpoint by wrapping it >>> with >>> >> >> > a SendToProcessor so you can add it to the LoadBalancerSupport >>> class. >>> >> >> > >>> >> >> > See how it goes and ask again tomorrow when I am back in the office >>> >> >> > and can better work. As I sit now with the laptop in the living >>> room. >>> >> >> > >>> >> >> > >>> >> >> >> >>> >> >> >> Thanks for help >>> >> >> >> >>> >> >> >> >>> >> >> >> >>> >> >> >> >>> >> >> >> On Thu, May 14, 2009 at 11:59 AM, Claus Ibsen < >>> [email protected] >>> >> > >>> >> >> wrote: >>> >> >> >> >>> >> >> >>> Hi >>> >> >> >>> >>> >> >> >>> There are load balancers with Camel >>> >> >> >>> http://camel.apache.org/load-balancer.html >>> >> >> >>> >>> >> >> >>> And there is a failover load balancer as well that can do a >>> simple >>> >> try >>> >> >> >>> the next endpoint until success kinda style. >>> >> >> >>> Its a bit primitive at the moment and we would like to improve >>> that >>> >> in >>> >> >> >>> the future. >>> >> >> >>> >>> >> >> >>> But it allows you to implement your own load balancer and do your >>> >> >> >>> strategy how you like it. >>> >> >> >>> >>> >> >> >>> Any feedback for features that could be needed for a more >>> advanced >>> >> >> >>> failover loadbalancer is much welcome. >>> >> >> >>> >>> >> >> >>> Ah the failover loadbalancer is not part of Camel 1.x. But you >>> can >>> >> >> >>> check the source code for 2.0 and create your own kinda to use in >>> >> 1.x. >>> >> >> >>> >>> >> >> >>> >>> >> >> >>> >> >>> https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/loadbalancer/ >>> >> >> >>> >>> >> >> >>> >>> >> >> >>> >>> >> >> >>> On Thu, May 14, 2009 at 11:45 AM, Nasim Anza < >>> >> [email protected] >>> >> >> > >>> >> >> >>> wrote: >>> >> >> >>> > Hi, >>> >> >> >>> > >>> >> >> >>> > I would like to implement the following route with Camel 1.6 : >>> >> >> >>> > >>> >> >> >>> > from("direct:endpointA") >>> >> >> >>> > .setHeader(HttpProducer.HTTP_URI).simple("http://myAddressA") >>> >> >> >>> > .to("http://xxxxxx") >>> >> >> >>> > .to("direct:endPointB") >>> >> >> >>> > >>> >> >> >>> > from("direct:endpointB") >>> >> >> >>> > .setHeader(HttpProducer.HTTP_URI).simple("http://myAddressB") >>> >> >> >>> > .to("http://xxxxxx") >>> >> >> >>> > .to("direct:endPointC") >>> >> >> >>> > >>> >> >> >>> > from("direct:endPointC") >>> >> >> >>> > .to("xquery:response.xml"); >>> >> >> >>> > >>> >> >> >>> > This route works fine if both URLs : http://myAddressA and >>> >> >> >>> > http://myAddressBare accessible and no error occurs during the >>> >> >> >>> > invocation. >>> >> >> >>> > Unfortunately, sometimes these services become unreachable and >>> I >>> >> >> would >>> >> >> >>> like >>> >> >> >>> > to try other URLs until getting valid answer: >>> >> >> >>> > >>> >> >> >>> > If an exception happens when calling the URL http:/:myAddressA, >>> I >>> >> >> would >>> >> >> >>> like >>> >> >> >>> > to attempt other URLs : myAddressA1, myAddressA2, ...until >>> getting >>> >> >> valid >>> >> >> >>> > HTTP response. >>> >> >> >>> > The same thing with myAddressB ==> myAddressB1, myAddressB2, >>> ... >>> >> >> >>> > >>> >> >> >>> > With java this could be simply coded like following : >>> >> >> >>> > >>> >> >> >>> > try >>> >> >> >>> > { >>> >> >> >>> > call_http(myAddressA) >>> >> >> >>> > } >>> >> >> >>> > catch(Throwable th) >>> >> >> >>> > { >>> >> >> >>> > try >>> >> >> >>> > { >>> >> >> >>> > call_http(myAddressA1) >>> >> >> >>> > } >>> >> >> >>> > catch(Exception x) >>> >> >> >>> > { >>> >> >> >>> > //Call addressA2 >>> >> >> >>> > .... >>> >> >> >>> > } >>> >> >> >>> > } >>> >> >> >>> > >>> >> >> >>> > I've tried the onException() mechanism and the >>> deadLetterChannel >>> >> >> >>> processor >>> >> >> >>> > but I never get working my route. >>> >> >> >>> > >>> >> >> >>> >>> >> >> >>> >>> >> >> >>> >>> >> >> >>> -- >>> >> >> >>> Claus Ibsen >>> >> >> >>> Apache Camel Committer >>> >> >> >>> >>> >> >> >>> Open Source Integration: http://fusesource.com >>> >> >> >>> Blog: http://davsclaus.blogspot.com/ >>> >> >> >>> Twitter: http://twitter.com/davsclaus >>> >> >> >>> >>> >> >> >> >>> >> >> > >>> >> >> > >>> >> >> > >>> >> >> > -- >>> >> >> > Claus Ibsen >>> >> >> > Apache Camel Committer >>> >> >> > >>> >> >> > Open Source Integration: http://fusesource.com >>> >> >> > Blog: http://davsclaus.blogspot.com/ >>> >> >> > Twitter: http://twitter.com/davsclaus >>> >> >> > >>> >> >> >>> >> >> >>> >> >> >>> >> >> -- >>> >> >> Claus Ibsen >>> >> >> Apache Camel Committer >>> >> >> >>> >> >> Open Source Integration: http://fusesource.com >>> >> >> Blog: http://davsclaus.blogspot.com/ >>> >> >> Twitter: http://twitter.com/davsclaus >>> >> >> >>> >> > >>> >> >>> >> >>> >> >>> >> -- >>> >> Claus Ibsen >>> >> Apache Camel Committer >>> >> >>> >> Open Source Integration: http://fusesource.com >>> >> Blog: http://davsclaus.blogspot.com/ >>> >> Twitter: http://twitter.com/davsclaus >>> >> >>> > >>> >>> >>> >>> -- >>> Claus Ibsen >>> Apache Camel Committer >>> >>> Open Source Integration: http://fusesource.com >>> Blog: http://davsclaus.blogspot.com/ >>> Twitter: http://twitter.com/davsclaus >>> >> > > > > -- > Claus Ibsen > Apache Camel Committer > > Open Source Integration: http://fusesource.com > Blog: http://davsclaus.blogspot.com/ > Twitter: http://twitter.com/davsclaus > -- Claus Ibsen Apache Camel Committer Open Source Integration: http://fusesource.com Blog: http://davsclaus.blogspot.com/ Twitter: http://twitter.com/davsclaus
