Thanks Claus for your help. Actually the problem I got is not related to the FailOverProcessor mechanism but in the global route: I would like that the result of a given HTTP endoint goes into another HTTP endpoint. For example the result of HTTP endpointA will be redirected to the HTTP endpoint B.... etc
I've pasted my route and my FailOver Processor on pastbin URL : http://mmo.pastebin.com/m7160e173 Please let me know if I have any error or mistake in the code. Note : the appliA1, appliA2, .appliX are webservices that return valid SOAP XMLs Thanks a lot for any help Nasmo On Sat, May 16, 2009 at 4:52 PM, Claus Ibsen <[email protected]> wrote: > 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 >
