In web services world, faults are not exceptions, but usually an xml payload. In the java world, faults would be like checked exceptions and errors runtime exceptions. However, distinguishing a fault from an out message by (instanceof Exception) is imho not sufficient
On Thu, Jul 9, 2009 at 07:35, Hadrian Zbarcea<hzbar...@gmail.com> wrote: > Hi, > > Comments inline. > > Hadrian > > On Jul 9, 2009, at 12:54 AM, Claus Ibsen wrote: > >> On Wed, Jul 8, 2009 at 9:52 PM, Hadrian Zbarcea<hzbar...@gmail.com> wrote: >>> >>> Hi, >>> >>> As we approach the 2.0, there is one more hanging issue I would like >>> addressed, if possible. It's the thorny issue of Faults and Exceptions >>> that >>> started in >>> http://issues.apache.org/activemq/browse/CAMEL-316 (see also the related >>> nabble thread linked in the issue description). >>> >>> I am less concerned about how the DefaultExchange is implemented and I >>> hope >>> to reach an agreement on what the Exchange api should be (please find the >>> list of Exchange methods below). >>> >>> As far as faults/exceptions are concerned, Roman thinks that the whole >>> concept of in/out/fault/exception is artificial, and only one payload >>> (message) api should be enough (Roman please correct me if I misinterpret >>> your position). My opinion is that we *must* distinguish between >>> persistent >>> (fault) and transient (exception) errors for the simple reason that they >>> have different semantics. As Roman correctly points out, faults are more >>> like outputs, have more of application level semantics and are normally >>> handled by the client, where exceptions (transient errors) are something >>> camel could try to recover from, without much knowledge about the >>> application. I think that the presence of fault in the camel api is not >>> due >>> to it being explicitly modeled by jbi and wsdl, as Roman suggests, and >>> Camel >>> simply copying that, but it's modeled in Camel for the same reason it's >>> modeled in jbi and wsdl, to differentiate transient from persistent >>> errors >>> in a non ambiguous way. >> >> I am one of the persons that would love the Camel Exchange / Message >> API to be a bit simpler. It has a fair shares of methods. >> >> Having listening and discussing with Hadrian on this and doing my own >> investigations and whatnot I do belive that Hadrian is absolutely >> right when it comes to FAULT. It has a good place in the API. I am +1 >> on having FAULT as we do now. >> >> The grief I have left is that the IN and OUT. It makes sense to have >> them and they provide a good value. However they have a big drawnback >> in how they are routed in Camel with the Pipeline processor, that >> mimics the pipes and filters EIP. And as a result the OUT will be used >> as IN >> in the next step in the route. So its not like you can steadily build >> up an OUT message on-the-fly during many steps in the route path. >> >> Example >> from("direct:start").process(new Processor()).to("log:foo"); >> >> a) From >> IN = Hello World >> OUT = null >> >> b) Processor >> IN Hello World >> OUT = Bye World >> >> c) Log >> IN = Bye World >> OUT = null >> > Yes, from an external observer's perspective, this is precisely what > happens. How we decide to store it, how many fields we need, is an > implementation detail of the DefaultExchange. I don't think the copy from > out/in is too expensive, but I would be ok with having only one field to > store the current message in DefaultExchange (I assume that's what you > propose). However, my question is about what the api should be. > > >> >> And then the getOut() method that lazy creates a new empty OUT message >> is also a pita, as it can lead to people loosing their messages if >> they do some System out logging of their own >> >> public void process(Exchange e) { >> System.out.println(exchange.getIn()); >> System.out.println(exchange.getOut()); >> // boom you lost your message when its routed to next node in route >> path, as getOut() created a new empty OUT message that will by used in >> the pipes and filters EIP routed with the Pipeline >> } >> >> We had this IN OUT discussion a while back and at that time we ended >> up with a compromise of having a hasOut() method so you should do, to >> be safe: >> System.out.println(exchange.getIn()); >> if (exchange.hasOut()) { >> System.out.println(exchange.getOut()); >> } >> >> Still a pita with the lazy creation IMHO. > > The lazyCreate methods are actually deprecated, and imho should be removed > now. This would eliminate the confusion. > > >>> >>> If we were to go with only get/setMessage() api, we would still need >>> methods >>> (or some ways) to distinguish between the kind of message we are dealing >>> with (in/out/fault/exception) so we'd only move the problem somewhere >>> else. >>> >>> So the question becomes if we leave the api the way it is, or we replace >>> the >>> get/setFault apis with get/setOut, in which case we'll need something >>> like: >>> boolean isFault(); >>> method in the Message api or keep the hasFault() method on the Exchange. >> >> Good question >> >> If you use OUT instead then we need to add a isFault() on the >> org.apache.camel.Message API that >> the IN message also implements. >> >> It could make sense to use OUT as well for FAULT. >> But how should the API look like to set an OUT as Fault? >> >> Something a like this? >> >> getOut().setBody("Unknown bank account number."); >> getOut().setFault(true); > > Not quite, I had something like this in mind (there is no setFault() > method): > getOut().setBody(java-lang-Exception-derivedObject); > > boolean isFault() { > return getBody() instanceof Exception; > } > > Personally I am ok with the limitation not being able to have an out of a > java.lang.Exception type (that would then be a Fault). I can't imagine a > case where an Exception would be an expected out, and in such cases one > could always serialize or wrap it. The fact that the Fault would be an > Exception type would be a camel convention that needs to be followed by all > components. > > Another option would be add header HAS_FAULT or something like that, in > which case both the out and the fault could be of any type. > > >> >>> >>> Thoughts? >>> >>> >>> ExchangePattern getPattern(); >>> void setPattern(ExchangePattern pattern); >>> >>> Object getProperty(String name); >>> <T> T getProperty(String name, Class<T> type); >>> void setProperty(String name, Object value); >>> Object removeProperty(String name); >>> Map<String, Object> getProperties(); >>> >>> Message getIn(); >>> void setIn(Message in); >>> >>> Message getOut(); >>> boolean hasOut(); >>> Message getOut(boolean lazyCreate); >>> void setOut(Message out); >>> >>> Message getFault(); >>> boolean hasFault(); >>> Message getFault(boolean lazyCreate); >>> void removeFault(); >>> // removeFault() is only used in one place >> >> +1 to remove it. You can just do setFault(null) instead. I will fix it >> asap. >> >> >> >>> >>> Exception getException(); >>> <T> T getException(Class<T> type); >>> void setException(Exception e); >>> boolean isFailed(); >>> >>> boolean isTransacted(); >>> boolean isRollbackOnly(); >>> >>> CamelContext getContext(); >>> >>> Exchange newInstance(); >>> Exchange copy(); >>> Exchange newCopy(boolean handoverOnCompletion); >>> void copyFrom(Exchange source); >>> >>> Endpoint getFromEndpoint(); >>> void setFromEndpoint(Endpoint fromEndpoint); >>> >>> UnitOfWork getUnitOfWork(); >>> void setUnitOfWork(UnitOfWork unitOfWork); >>> >>> String getExchangeId(); >>> void setExchangeId(String id); >>> >>> void addOnCompletion(Synchronization onCompletion); >>> >>> >>> >>> >>> >> >> >> >> -- >> Claus Ibsen >> Apache Camel Committer >> >> Open Source Integration: http://fusesource.com >> Blog: http://davsclaus.blogspot.com/ >> Twitter: http://twitter.com/davsclaus > > -- Cheers, Guillaume Nodet ------------------------ Blog: http://gnodet.blogspot.com/ ------------------------ Open Source SOA http://fusesource.com