Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Ode Wiki" for change 
notification.

The following page has been changed by MatthieuRiou:
http://wiki.apache.org/ode/Jacob

------------------------------------------------------------------------------
  
  In order to save the process to disk, we need to end the current thread of 
control which means popping both stack frames. To do this we have no choice but 
to require the implementation of Wait and Sequence to "cooperate" with this 
requirement thereby greatly complicating the implementation of those 
constructs. This also means that the "natural" implementation model cannot be 
used directly.
  
- JACOB aims to solve this problem by providing an alternate "natural" model 
that allows execution state to be suspended /without cooperation from the 
implementation classes/. The idea in JACOB is to flatten the call stack and 
rely on explicit communication channels to handle control flow. We now consider 
a simplified JACOB representation of our three BPEL activities:
+ JACOB aims to solve this problem by providing an alternate "natural" model 
that allows execution state to be suspended ''without cooperation from the 
implementation classes''. The idea in JACOB is to flatten the call stack and 
rely on explicit communication channels to handle control flow. We now consider 
a simplified JACOB representation of our three BPEL activities:
  
  {{{#!java
  class Empty  {
@@ -241, +241 @@

  
  == JavaClosure / Abstraction ==
  
- From Wikipedia: "A closure combines the code of a function with a special 
lexical environment bound to that function (scope). Closure lexical variables 
differ from global variables in that they do not occupy the global variable 
namespace. They differ from object oriented object variables in that they are 
bound to functions, not objects.". Normally closures aren't supported in Java 
so JavaClosure tries to feels that gap. But it's not a true closure anyway, 
which makes thing easier. Closures in Jacob are statically coded, whereas in 
most languages supporting closures these are dynamic. So basically in Jacob, a 
closure is expected to implement some methods and provides other utility 
methods to manipulate channels and replicate itself.
+ From Wikipedia: "A closure combines the code of a function with a special 
lexical environment bound to that function (scope). Closure lexical variables 
differ from global variables in that they do not occupy the global variable 
namespace. They differ from object oriented object variables in that they are 
bound to functions, not objects.". Normally closures aren't supported in Java 
so 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/JavaClosure.java
 JavaClosure] tries to feel that gap. But it's not a true closure anyway, which 
makes thing easier. Closures in Jacob are statically coded, whereas in most 
languages supporting closures these are dynamic. So basically in Jacob, a 
closure is expected to implement some methods and provides other utility 
methods to manipulate channels and replicate itself.
  
- Abstraction is just a closure that requires the implementation of only one 
method: self(). As /all activities inherit from Abstraction/ they're all 
supposed to implement their main processing in this self() method. Their 
initialization occur in their respective constructors.
+ 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/Abstraction.java
 Abstraction] is just a closure that requires the implementation of only one 
method: self(). As ''all activities inherit from 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/Abstraction.java
 Abstraction]'' they're all supposed to implement their main processing in this 
self() method. Their initialization occur in their respective constructors.
  
  == Method Lists (MLs) ==
  
@@ -271, +271 @@

  
  == VPU and Soup ==
  
- The VPU is where all the Jacob processing is occuring. When an JavaClosure is 
injected inside the VPU, it's actually registered as a Reaction, which is just 
wrapping the closure with the method to call on the closure to execute it (in 
our case always the self() method as we're only dealing with Abstraction 
instances).
+ The 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/vpu/JacobVPU.java
 VPU] is where all the Jacob processing is occuring. When an JavaClosure is 
injected inside the VPU, it's actually registered as a 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/soup/Reaction.java
 Reaction], which is just wrapping the closure with the method to call on the 
closure to execute it (in our case always the self() method as we're only 
dealing with Abstraction instances).
  
- The Soup is just a container for all the artifacts managed by the VPU (mostly 
channels and reactions) to organize them in queues where artifacts can be 
pushed and popped. It also records some execution statistics.
+ The 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/soup/Soup.java
 Soup] (and its implementation 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/vpu/FastSoupImpl.java
 FastSoupImpl]) is just a container for all the artifacts managed by the VPU 
(mostly channels and reactions) to organize them in queues where artifacts can 
be pushed and popped. It also records some execution statistics.
  
- So the VPU main processing is just dequeuing a reaction from the soup and 
executing it. That's all (check JacobVPU.execute(), you'll see that I'm not 
lying). However when the Abstraction (usually an activity) gets executed the 
following things can happen:
+ So the VPU main processing is just dequeuing a reaction from the soup and 
executing it. That's all (check 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/jacob/src/main/java/com/fs/jacob/vpu/JacobVPU.java
 JacobVPU].execute(), you'll see that I'm not lying). However when the 
Abstraction (usually an activity) gets executed the following things can happen:
  
  * if other abstractions (usually other activities) are created, they will be 
appended to the reaction queue,
  * if new channels are created, they will be saved for later usage,
@@ -338, +338 @@

  </process>
  }}}
  
- Everything starts with a receive. So our entry point here in our 
Jacob-focused discussion is going to be 
[BpelProcess.PartnerLinkMyRoleImpl.inputMsgRcvd|http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/BpelProcess.java].
 The code that matters to us now is the following (executed when a message is 
targeted at a createInstance receive):
+ Everything starts with a receive. So our entry point here in our 
Jacob-focused discussion is going to be 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/BpelProcess.java
 BpelProcess].PartnerLinkMyRoleImpl.inputMsgRcvd(). The code that matters to us 
now is the following (executed when a message is targeted at a createInstance 
receive):
  
  {{{#!java
      BpelRuntimeContextImpl instance = createRuntimeContext(newInstance, new 
PROCESS(_oprocess), messageExchange);
@@ -355, +355 @@

      }
  }}}
  
- The process itself get injected. When executed, PROCESS just instantiates a 
scope to control the execution of its child activity and starts listening on 
compensation and completion channel. From the process we go to a scope, then 
our main sequence and finally our receive.
+ The process itself get injected. When executed, 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/PROCESS.java
 PROCESS] just instantiates a scope to control the execution of its child 
activity and starts listening on compensation and completion channel. From the 
process we go to a scope, then our main sequence and finally our receive.
  
- Receives are just mapped to a pick onMessage so its Jacob implementation 
should be looked for in PICK. The PICK is just about isolating the right 
correlations and selecting a message for it, then waiting for the message. In 
our createInstance case we'll be more interested in the following code, located 
in BpelRuntimeContextImpl.select() (and called by PICK):
+ Receives are just mapped to a pick onMessage so its Jacob implementation 
should be looked for in 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/PICK.java
 PICK]. The 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/PICK.java
 PICK] is just about isolating the right correlations and selecting a message 
for it, then waiting for the message. In our createInstance case we'll be more 
interested in the following code, located in 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/BpelRuntimeContextImpl.java
 BpelRuntimeContextImpl].select() (and called by PICK):
  
  {{{#!java
      if (_instantiatingMessageExchange != null && _dao.getState() == 
ProcessState.STATE_READY) {
@@ -382, +382 @@

      });
  }}}
  
- That's where things really start. When injected, this abstraction just calls 
the response channel for our receive. The other side of this channel is 
implemented as an ML in the PICK:
+ That's where things really start. When injected, this abstraction just calls 
the response channel for our receive. The other side of this channel is 
implemented as a ML in the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/PICK.java
 PICK]:
  
  {{{#!java
      object(false, new PickResponseML(_pickResponseChannel) {
@@ -402, +402 @@

  
  The parent sequence gets notified almost immediately after the 
onRequestRcvd() methods finishes.
  
- Now how does our sequence gets back the control? Well, once again, let's look 
at the ML, the other side of the channel. As one of the most important job of 
the VPU is matching channels invocations and MLs, we'll get to the sequence byt 
its ParentScopeML implementation:
+ Now how does our sequence gets the control back? Well, once again, let's look 
at the ML, the other side of the channel. As one of the most important job of 
the VPU is matching channels invocations and MLs, we'll get to the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/SEQUENCE.java
 sequence] by its ParentScopeML implementation:
  
  {{{#!java
  class SEQUENCE extends ACTIVITY {
@@ -435, +435 @@

  }
  }}}
  
- The method that will get executed is of course the completed() method. It 
simply completes if a fault has been thrown, a termination has been requested 
and if no child activities remain. Being of an optimistic nature, we'll check 
what happens when everything goes just fine. In this second case a remaining 
activity is removed and the SEQUENCE abstraction itself is reinstantiated. 
Which leads us to what the SEQUENCE does:
+ The method that will get executed is of course the completed() method. It 
simply completes if a fault has been thrown, a termination has been requested 
and if no child activities remain. Being of an optimistic nature, we'll check 
what happens when everything goes just fine. In this second case a remaining 
activity is removed and the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/SEQUENCE.java
 SEQUENCE] abstraction itself is reinstantiated. Which leads us to what the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/SEQUENCE.java
 SEQUENCE] does:
  
  {{{#!java
    public void self() {
@@ -449, +449 @@

  
  As you can see, it just instantiates the next child abstraction and also 
another abstraction named ACTIVE. So what's this ACTIVE that we've already seen 
a bit before? Well, it's just the abstraction that keeps on following child 
activities when they execute. It's more like a convention on all 
containment-based activity in PXE (while, sequence, pick, ...) that the main 
activity abstraction just kicks off the processing. Then an ACTIVE (also 
sometimes called WAITER) abstraction takes care of following the children.
  
- Rolling on to the next step, we've just instantiated an abstraction for the 
while in our example process, as it's the next child of the sequence. So what 
happens there?
+ Continuing to the next step, we've just instantiated an abstraction for the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/WHILE.java
 while] in our example process, as it's the next child of the sequence. So what 
happens there?
  
  {{{#!java
    public void self() {
@@ -472, +472 @@

    }
  }}}
  
- Now you should be getting more familiar with that sort of code. First step is 
evaluating the while condition. If it turns out it's true, then a child 
abstraction gets created as well as a WAITER to follow its execution. The 
WAITER implementation is again pretty straightforward:
+ Now you should be getting more familiar with that sort of code. First step is 
evaluating the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/WHILE.java
 while] condition. If it turns out it's true, then a child abstraction gets 
created as well as a WAITER to follow its execution. The WAITER implementation 
is again pretty straightforward:
  
  {{{#!java
    private class WAITER extends BpelAbstraction {
@@ -507, +507 @@

    }
  }}}
  
- Termination and compensation aren't doing anything really interesting. 
Completion, just like for the sequence, re-instantiates the WHILE abstraction. 
And that's how we get our loop, by re-instantiating the main WHILE abstraction 
(again evaluating the condition and creating a child if it's true).
+ Termination and compensation aren't doing anything really interesting. 
Completion, just like for the sequence, re-instantiates the 
[http://svn.apache.org/repos/asf/incubator/ode/scratch/pxe/bpel-runtime/src/main/java/com/fs/pxe/bpel/runtime/WHILE.java
 WHILE] abstraction. And that's how we get our loop, by re-instantiating the 
main WHILE abstraction (again evaluating the condition and creating a child if 
it's true).
  
  Finally, when the while condition becomes false, it notifies its parent 
channel. The sequence then goes to our last activity: reply. As expected, the 
reply replies, just sending the variable content and notifying its parent for 
completion. The sequence has no more children to execute so it also notifies 
its own parent, which is the process. We then just declare the process to be 
completed and that's it! We're done!
  

Reply via email to