12 Replies Latest reply on May 13, 2008 3:29 AM by tom.baeyens

    adding activity instances

    tom.baeyens

      as you know i'm adding activity instances, this includes variable declarations and timers.

      the improvements are going to be significant:

      * support for both models with and without activity instances.
      * customizable activity instance types (as long as you stick within the PVM schema)
      * declarative support for timers
      * timers require activity instances to synchronize the external trigger with potential timer triggers
      * automatic scope creation and destruction during runtime operation. in case you didn't notice, this is a *really* cool feature
      * variable declarations with initial values on process definitions and on nodes.
      * variable propagation to outer scope upon scope destruction
      * sub process instance support

      i'm past the research point. in order to spread eventual merge work and to make sure i can continue working over the weekend, i'll be exceptionally breaking the complete sources.

      hopefully the great new features make up for the mess i'm creating :-)

        • 1. Re: adding activity instances
          aguizar

           

          i'll be exceptionally breaking the complete sources.

          I just noticed that, the hard way :-P I'll work on the jBPM 3 timer in the meantime...

          • 2. Re: adding activity instances
            tom.baeyens

            check out this

            /*
             +-process-----------------------+
             | |
             | ${customer} = coca-cola |
             | ${address} = usa |
             | ${size} = big |
             | |
             | +-composite-----------------+ |
             | | | |
             | | ${form} = sparkling | |
             | | ${form} = sparkling | |
             | | | |
             | | +-initial---------------+ | |
             | | | ${form} = sparkling | | |
             | | | ${size} = extra large | | |
             | | | ${sugar} = lots | | |
             | | +-----------------------+ | |
             | +---------------------------+ |
             +-------------------------------+
             */
             ProcessDefinition processDefinition = ProcessFactory.build()
             .variable("customer", "coca-cola")
             .variable("address", "usa")
             .variable("size", "big")
             .compositeNode("composite").behaviour(new WaitState())
             .variable("form", "liquid")
             .variable("address", "conneticut")
             .transition().to("end")
             .compositeNode("initial").behaviour(new WaitState())
             .initial()
             .variable("form", "sparkling")
             .variable("size", "extra large")
             .variable("sugar", "lots")
             .transition().to("composite")
             .compositeEnd()
             .compositeEnd()
             .node("end").behaviour(new WaitState())
             .done();
            
             Execution execution = processDefinition.startExecution();
            
             Set<String> expectedKeys = new HashSet<String>();
             expectedKeys.add("customer");
             expectedKeys.add("address");
             expectedKeys.add("size");
             expectedKeys.add("form");
             expectedKeys.add("sugar");
             assertEquals(expectedKeys, new HashSet<String>(execution.getVariableKeys()));
            
             Map<String, Object> expectedVariables = new HashMap<String, Object>();
             expectedVariables.put("customer", "coca-cola");
             expectedVariables.put("address", "conneticut");
             expectedVariables.put("size", "extra large");
             expectedVariables.put("form", "sparkling");
             expectedVariables.put("sugar", "lots");
             assertEquals(expectedVariables, new HashMap<String, Object>(execution.getVariables()));
            


            cool, no ?

            • 3. Re: adding activity instances
              tom.baeyens

              apologies, alejandro.

              this went way further then anticipated at first. it's a necessary improvement.

              one of the important improvements (also for the enterprise timers) is that the timers are now navigatable in the java object model as well.

              this will make it much better possible to create a clean cut test environment without needing a database.

              that way we can have test scenarios and specify inbetween signals which timer has to fire...

              if then koen can attach that to the debugger and link it with the graphical information that is going to be awsome.

              i hope that prospect makes up a bit for the trouble.

              • 4. Re: adding activity instances
                tom.baeyens

                damn. didn't finish the test yet.

                i still have to add taking the transitions out of the scope and verify that the scopes get destroyed and that scoping then works as expected...

                • 5. Re: adding activity instances
                  tom.baeyens

                  alejandro,

                  can you make a patch file (e.g. with eclipse), then i can have a look at the changes and apply them once i'm done with this refactoring

                  • 6. Re: adding activity instances

                    Tom,

                    Slightly off-topic...

                    Have you thought at all about scopes for expensive-to-create data that's private to a particular configuration/ObjectReference of a particular Activity, but global to all instances ? I've been running into this with JBPM.
                    Consider, for instance, retention of an EJB home interface on a rapid-fire Activity that needs to call the EJB.
                    The data shouldn't be at process level.
                    It may be persistent - but usually not.

                    -Ed Staub

                    • 7. Re: adding activity instances
                      tom.baeyens

                      so this was the result of the variable declaration test. it also shows that if there is an activity instance on the current node, then you *have* to provide the signal through the activity instance instead of through the execution

                      /*
                       +-process-----------------------+
                       | |
                       | ${customer} = coca-cola |
                       | ${address} = usa |
                       | ${size} = big |
                       | |
                       | +-composite-----------------+ |
                       | | | |
                       | | ${form} = sparkling | |
                       | | ${form} = sparkling | |
                       | | | |
                       | | +-initial---------------+ | |
                       | | | ${form} = sparkling | | |
                       | | | ${size} = extra large | | |
                       | | | ${sugar} = lots | | |
                       | | +-----------------------+ | |
                       | +---------------------------+ |
                       | |
                       | +-end---+ |
                       | +-------+ |
                       +-------------------------------+
                       */
                       ProcessDefinition processDefinition = ProcessFactory.build()
                       .variable("customer", "coca-cola")
                       .variable("address", "usa")
                       .variable("size", "big")
                       .compositeNode("composite").behaviour(new WaitState())
                       .variable("form", "liquid")
                       .variable("address", "conneticut")
                       .transition().to("end")
                       .compositeNode("initial").behaviour(new WaitState())
                       .initial()
                       .variable("form", "sparkling")
                       .variable("size", "extra large")
                       .variable("sugar", "lots")
                       .transition().to("composite")
                       .compositeEnd()
                       .compositeEnd()
                       .node("end").behaviour(new WaitState())
                       .done();
                      
                       Execution execution = processDefinition.startExecution();
                      
                       Map<String, Object> expectedVariables = new HashMap<String, Object>();
                       expectedVariables.put("customer", "coca-cola");
                       expectedVariables.put("address", "conneticut");
                       expectedVariables.put("size", "extra large");
                       expectedVariables.put("form", "sparkling");
                       expectedVariables.put("sugar", "lots");
                       assertEquals(expectedVariables, new HashMap<String, Object>(execution.getVariables()));
                      
                       execution.getActivityInstance().signal();
                      
                       expectedVariables = new HashMap<String, Object>();
                       expectedVariables.put("customer", "coca-cola");
                       expectedVariables.put("address", "conneticut");
                       expectedVariables.put("size", "big");
                       expectedVariables.put("form", "liquid");
                       assertEquals(expectedVariables, new HashMap<String, Object>(execution.getVariables()));
                      
                       execution.getActivityInstance().signal();
                      
                       expectedVariables = new HashMap<String, Object>();
                       expectedVariables.put("customer", "coca-cola");
                       expectedVariables.put("address", "usa");
                       expectedVariables.put("size", "big");
                       assertEquals(expectedVariables, new HashMap<String, Object>(execution.getVariables()));
                      




                      • 8. Re: adding activity instances
                        tom.baeyens

                         

                        "estaub" wrote:
                        Tom,

                        Slightly off-topic...

                        Have you thought at all about scopes for expensive-to-create data that's private to a particular configuration/ObjectReference of a particular Activity, but global to all instances ? I've been running into this with JBPM.
                        Consider, for instance, retention of an EJB home interface on a rapid-fire Activity that needs to call the EJB.
                        The data shouldn't be at process level.
                        It may be persistent - but usually not.

                        -Ed Staub


                        you mean caching the activities them selves or their data ?

                        that is a hard one. as process definition information is in the db and loaded with hibernate.

                        i thought a long time about just caching the activities (or actions). but i am reluctant to start building my own caching for this.

                        do you see any alternatives ?

                        • 9. Re: adding activity instances
                          kukeltje

                          [quopte]it also shows that if there is an activity instance on the current node, then you *have* to provide the signal through the activity instance instead of through the execution

                          • 10. Re: adding activity instances

                             

                            "tom.baeyens@jboss.com" wrote:
                            "estaub" wrote:
                            Tom,

                            Slightly off-topic...

                            Have you thought at all about scopes for expensive-to-create data that's private to a particular configuration/ObjectReference of a particular Activity, but global to all instances ? I've been running into this with JBPM.
                            Consider, for instance, retention of an EJB home interface on a rapid-fire Activity that needs to call the EJB.
                            The data shouldn't be at process level.
                            It may be persistent - but usually not.

                            -Ed Staub


                            you mean caching the activities them selves or their data ?

                            that is a hard one. as process definition information is in the db and loaded with hibernate.

                            i thought a long time about just caching the activities (or actions). but i am reluctant to start building my own caching for this.

                            do you see any alternatives ?


                            Most of the use-cases I see shouldn't be persistent, and don't need to be cluster-aware, so caching may not be relevant. Consider cases like these:

                            - a config parameter points at read-only metadata in a database that need only be looked up once, then used over all process instances

                            - a config parameter contains the JNDI name for a J2EE SLSB that is not hot-redeployed. Its home interface may be kept and reused across all process instances.

                            I'm sure you can think of many more cases.

                            I think the lifecycle is similar to that for the in-memory representation of the process definition itself. I don't have a good enough understanding of the lifecycle of ObjectReference, Activity, etc. to know where the best place to hook in these objects. From the Activity implementation's perspective, it may just look like another Variable scope, that is populated when the expected variables are absent, indicating that this is a "first encounter".

                            -ed

                            • 11. Re: adding activity instances
                              tom.baeyens

                               

                              "estaub" wrote:
                              Most of the use-cases I see shouldn't be persistent, and don't need to be cluster-aware, so caching may not be relevant.
                              ...

                              I think the lifecycle is similar to that for the in-memory representation of the process definition itself. I don't have a good enough understanding of the lifecycle of ObjectReference<Activity>


                              spot on.

                              An object reference has 3 ways of referencing an object (e.g. an activity impl):

                              * a wire descriptor. this is information that can instantiate and wire a java object based on descriptor information using reflection.

                              * an expression. using EL to resolve an expression to fetch an object.

                              * a direct pointer to an object. this is exactly what you're talking about. We can "cache" the object fetched through wiring or expression resolving here. (the direct object it also can be used in persistent mode, where it is mapped with hibernate as an 'any')


                              though i also see and agree with the in-memory use cases, i estimate that the majority of use cases are persistent.

                              • 12. Re: adding activity instances
                                tom.baeyens

                                 

                                "kukeltje" wrote:
                                it also shows that if there is an activity instance on the current node, then you *have* to provide the signal through the activity instance instead of through the execution


                                This is very good.... lots of confusion here with users, and undertermined behaviour (in their view) when signalling the execution instead of the activity instance


                                ok.

                                i corrected your quoting confusion :-)