- From: Ricky Ho <riho@cisco.com>
- Date: Thu, 22 May 2003 09:11:11 -0700
- To: Assaf Arkin <arkin@intalio.com>
- Cc: public-ws-chor@w3.org
Assaf, Can you confirm my understanding from your previous message ? When a caller invoke a service (which is implemented in BPEL using <receive>) and pass-in a transaction context. The caller will receive a SOAP fault if any of the following happens .... a) The <receive> is NOT defined within a <scope> b) The <receive> is NOT the first activity of that <scope> AND some "different" context has already been established. (e.g. There is an <invoke> preceding this <receive>, or there is another <receive> preceding this <receive>) Best regards, Ricky >Ricky Ho wrote: > >> >>There are a couple of issues .... >> >>Lets say in the following process >> >><process> >> <sequence> >> .... >> <receive/> >> .... >> <reply/> >> .... >> <receive/> >> .... >> <reply/> >> .... >> </sequence> >></process> >> >>1) Lets say the first <receive> pass in a transaction context. What is >>the "scope of work" ? Between the first request and first reply ? >>or everything after the first receive ? > >That depends on how you define the importing of the context. > >If you define the scope as the entire sequence then it will start with the >first receive but it will end all the work after the last activity has >occurred (i.e. after the second reply). The sender is not just waiting for >a reply, the sender is also waiting to later on either receive a >completed, exited, or failed message indicating that all further work done >after the reply has completed/failed. > >If the scope is for a single activity than only that activity is >performed, but again after the reply is sent you still need to send >completed/exited/failed which you could potentially piggyback on the reply >message (though not allowed in WS-TX currently). > > >>2) Lets say after receiving the first <reply>, the caller want to commit >>the transaction. What scope of work has been committed ? Does the >>caller wait for this whole process to be completed before the caller's >>transaction can commit successfully ? > >If we are talking BA then there are two modes: either you tell the process >when all work has been completed so it can wrap up things on its side and >send a completed/exited message, or you wait for it to tell you when it >completes and then wait for all others to tell you they completed. In case >of aborting, you would just tell working scopes to cancel and completed >scopes to compensate. > >The important thing here is that you should say what you mean and mean >what you say. If what you meant is that no work could be completed unless >you received two requests, then that's what should happen. If someone >tries to commit before you completed all the work you consider this to be >an inconsistent state and vote to rollback. This means that you will never >do part of the work - either all or nothing. > >If what you meant is that only some work needs to be done and the rest is >optional, you should write it as such, perhaps by using an event handler. > > >>3) If instead the caller want to cancel the transaction. How does the >>process cancel its work ? Where is the compensation handler defined ? > >Since you haven't yet completed the sequence you can't compensate for it. >Instead you get a terminate fault and handle it. However, since you >already did some activities you may have nested scopes with their own >compensation handlers which you would invoke from the event handler of the >sequence. > > >>4) What if the second <receive> pass in a different context ? (the only >>way to prevent this happening is to use the context itself as the >>correlation set) > >Good question. > >In EJB if you have a session bean and you call it twice in two different >transactions then the access would be serialized or you would get an >error. I don't exactly remember which case is true, but you won't get two >invocations from two transactions for the same bean if one transaction has >not completed yet. > >So I would tend to believe that the rule should be that all incoming >messages should either be part of the same scope, part of a child scope >(if that activity is defined as part of a child scope), or not associated >with any scope. But it can't be part of a different scope unless it >observes a parent-child relationship. > >>>So it would work like the transaction attribute requires in an EJB bean. >>>Either you start a new transaction if none was started by the caller, or >>>you participate in the caller's transaction. >> >> >>BPEL <Receive> is quite different from the EJB scenario. The EJB doesn't >>have a pre-establish transaction context, it either starts a new context >>or inherit the caller's context. In EJB, you never run into the >>situation of the above question 4. > >I think you do. If you think of a session bean, once you access it from a >transaction it is owned by that transaction until it commits. You can keep >calling it from that transaction, but you can't call it from another >transaction at the same time. That would just confuse the hell out of it ;-) > >The case here is of course more complex because you have more explicit >sequencing rules, a problem you also have with EJB but don't notice >because there is no language to write the behavior, and because you have >nesting. > >>>For atomic transactions you don't need prepare or commit, you are >>>working at a higher level than the code and all that needs to be >>>prepared or committed should be done by the engine for you. For BA >>>transactions you don't have prepare or commit, every response is an >>>indication that all previous steps have been completed (prepared and >>>committed). You do need a way to cancel, but this can be done by a fault >>>handler (the terminate fault). And you do need a way to compensate and >>>this is done by a compensation handler. >> >> >>I'm talking about BA, not atomic. Effectively, you restrict the choices >>by forcing every scope of work must be compensatable. > >>Lets say I'm an airline company. I don't want to reserve the seat for a >>lengthy period and later cancel it when the passenger change his >>mind. So my strategy is to only book the seat when the customer commits >>its purchase. After that, I don't refund (so not compensatable from the >>passenger's perspective). >>The original state of the seat is "available". When the passenger invoke >>my "TicketBookingService", the seat is marked "potentially-booked". When >>the transaction commit successfully, the seat status to be >>"booked". After that, it is non-compensatable. >> >>How do I achieve this if I only have the CompensationHandler ? > >You have one activity (possibly a sequence) that changes the seat >assignment to "reserved". Afterwards it can be cancelled by the customer >or it can be cancelled because the customer did not send a booking request >within a well defined time frame (e.g. use a switch with message event and >time-out event). If it gets cancelled then you invoke the compensation of >the first activity changing it back to "available". If you do receive a >request to book the seat you proceed to the next step. At this point the >state is "booked" and there is no compensation associated with the >previous state. > >I think as a basic shell you would have to write something like: > >process > compensationHandler > empty > (note: very important to write something here so it doesn't > automatically compensate reserveToBook) > > receive reservation request > scope name=reserveToBook > invoke name=reserve > compensationHandler > ... change back to available > ... this is where we talk to a service that changes state to reserved > pick > branch 1: booking request > change to booked > branch 2: alarm > throw a fault >do anything else after reservation > >arkin > >> >> >>Rgds, Ricky > > > >-- >"Those who can, do; those who can't, make screenshots" > >
Received on Thursday, 22 May 2003 12:11:31 UTC