8 Replies Latest reply on Nov 28, 2005 7:49 PM by pjmvn

    Use Object Factory - Bean

    pjmvn

      I have read Chapter 6: Configuration, 6.5: Object Factory and some example from source.
      I know the Object Factory(bean) can allow we create an according object.
      But i don't know where to insert(in GPD) to my project.
      The GPD IDE does not support it. And have no example about it.
      Please give me an idea or example.
      Thanks.

        • 1. Re: Use Object Factory - Bean
          pjmvn

          Please help me.

          • 2. Re: Use Object Factory - Bean
            kentest

            what kind of document do you read about jBPM?
            I cann't find it what you say in the userguide of jBPM.

            • 3. Re: Use Object Factory - Bean
              pjmvn

              In document of jBPM 3.1-alpha1

              • 4. Re: Use Object Factory - Bean
                koen.aers

                Can you point me to the exact document? In my 3.1 alpha1 build chapter 6 is about persistence...

                Regards,
                Koen

                • 5. Re: Use Object Factory - Bean
                  pjmvn

                  Here is release note :

                  Release Notes - JBoss jBPM - Version jBPM 3.1 alpha 1
                  (to view the issues, click the links or point your browser to http://jira.jboss.com/jira/browse/JBPM-{ISSUE-NUMBER}
                  
                  Main updates from 3.0.x to 3.1
                  Asynchronous continuations (see user guide Chapter 'Asynchronous continuations')
                  Configuration framework (see user guide Chapter 'Configuration')
                  Task instance variables (see user guide Chapter 'Task Management' section 'Task controllers')
                  TaskInstanceFactory replaced the task instance class configuration (see user guide Chapter 'Task Management' section 'Customizing task instances')
                  

                  Here chapter:


                  Chapter 6. Configuration
                  JBoss jBPM includes a configuration framework that serves two purposes:
                  
                  Provides abstraction of the environment that surrounds jBPM. Examples of environments are a web application, a plain java standalone application, a unit test, an application server, ... The code that you write to address jBPM will be the same in all environments. The behaviour of that code can be configured in a configuration file, rather then changing the code that uses jBPM.
                  Allows us to provide default configurations for 3 target environments: a unit test, a web application and an enterprise environment. Since jBPM includes a lot of configurable and customizable parts, it can be a challenge to get them all set up for your environment. With this configuration framework we are able to provide a set of configurations for each of the 3 target environments. You can use one of those configurationsets as a starting point to configure jBPM for your specific environment. See also Section 6.2, ?Configuration environments?
                  
                  Note that you don't really need this configuration framework to use jBPM. But it can help you with getting the jBPM persistence, asynchronous messaging and scheduling configured easily in all kinds of possible combinations.
                  
                  You'll see similar concepts in other lightweight application frameworks such as the jboss microcontainer or spring. We opted to provide our own mini framework cause 1) we only need a small subset of those features. So we created a minimal taylored version of some of the concepts that you'll find in these frameworks. and 2) The features, concepts and responsibilities of these frameworks are still evolving and settling. 3) The frameworks at hand didn't give us all the functionality that we needed.
                  
                  The configuration framework is composed of 3 components: Section 6.3, ?Context builder? Section 6.5, ?Object factory? and Section 6.4, ?Thread context?. But the first two sections will describe how a user interacts with the configuration framework.
                  
                  6.1. The configuration framework
                  While the usage of the configuration framework is optional, there are is one basic usage scenarios that we recommend to our users. Also some of the internal jbpm components use the configuration framework to be easier configurable.
                  
                  6.1.1. Client context
                  The only usage where users directly use the configuration framework is for persistent client workflow operations. The recommended approach is the following user code. Let's take the creation of a new process instance as an example and then step through the highlights of what the configuration framework does for you.
                  
                  ContextBuilder contextBuilder = ContextBuilder.create("client");
                  try {
                   contextBuilder.begin();
                  
                   GraphSession graphSession = JbpmSessionContext.getGraphSession();
                   ProcessDefinition myProcess = graphSession.findLatestProcessDefinition("myprocess");
                   ProcessInstance processInstance = new ProcessInstance(myProcess);
                   processInstance.signal();
                   graphSession.saveProcessInstance(processInstance);
                  
                  } finally {
                   contextBuilder.end();
                  }
                  First of all, ContextBuilder.create("client") will fetch a client context builder from the object factory as it is configured in the jbpm.cfg.xml configuration file. The default configuration looks like this:
                  
                  <context-builder name="client">
                   <bean class="org.jbpm.tc.hibernate.HibernateSessionFactoryInterceptor" singleton="true" />
                   <bean class="org.jbpm.tc.hibernate.HibernateSessionInterceptor" singleton="true" />
                   <bean class="org.jbpm.tc.db.JbpmSessionInterceptor" singleton="true" />
                   <bean class="org.jbpm.tc.msg.MessageServiceInterceptor" singleton="true" />
                   <bean class="org.jbpm.tc.scheduler.SchedulerServiceInterceptor" singleton="true" />
                   <bean class="org.jbpm.tc.hibernate.HibernateTransactionInterceptor" singleton="true" />
                  </context-builder>
                  
                  What this means is that in the contextBuilder.begin(), first the hibernate session factory will be looked up from a static repository with lazy initialization, then a hibernate session will be created with the hibernate session factory. After that, the jbpm sessions (like e.g. the GraphSession, TaskMgmtSession,...) are created. Then the jbpm internal message service is created that uses the same hibernate session as the persistence sessions. Similar for the scheduler. Then a transaction is started.
                  
                  Inside of the context block, you can see that the GraphSession is obtained with JbpmSessionContext.getGraphSession(). This is because one of the interceptors has made the GraphSession available in the thread local context and the JbpmSessionContext provides the convenience methods to work with the JbpmSession objects in the thread local context.
                  
                  The contextBuilder.end() will commit the transaction on the jdbc connection that was created by hibernate unless the JbpmSessionContext.setRollbackOnly() was called. In the latter case, a rollback is issued on the jdbc transaction. After transaction completion (commit or rollback) all the other interceptors do their respective clean up.
                  
                  6.1.2. Internal jBPM usages
                  There are 2 other situations where similar persistence blocks are used inside of the jbpm code: The SchedulerThread and the CommandExecutor. Both of these components will need to perform persistent operations on process executions in the background. So these components will use the same approach. Therefore, their persistence is also configurable in the jbpm.cfg.xml configuration file. See ??? and ??? for more information.
                  
                  Another internal jbpm usage of the configuration framework is inside the GraphSession.saveProcessInstance(ProcessInstance) operation. During that operation, a number of things have to be done. The most important part is the hibernate save. The hibernate saving of the process instance will compare the state of the java object with the database state and issue the SQL statements to bring the database in the same state as the process instance. The hibernate save operation cascades through all of the process instance object graph. But there are a few other things that will have to be done as well. E.g. scheduling timers and sending messages. Since we want it to be configurable how messages and timers are handled, this is abstracted. During process execution, messages and timers are stored (non-persistent) somewhere in the process instance object graph. In the saveProcessInstance operation, these will be fetched and handled. To make the handling of such extra responsibilities inside of the saveProcessInstance method configurable, we used the configuration framework for this as well.
                  
                  6.2. Configuration environments
                  TODO describe the 3 target environments (pojo, pojo with persistence and enterprise) and the configurations that are in the jbpm.cfg.xml for these configurations.
                  
                  6.3. Context builder
                  This the simplest interceptor framework that doesn't require any bytecode manipulation or precompilation. There are just 2 classes: ContextInterceptor and ContextBuilder. ContextInterceptor is an interface with a begin and end method like this:
                  
                  public interface ContextInterceptor extends Serializable {
                   void begin();
                   void end();
                  }
                  A ContextBuilder can be created with a list of ContextInterceptors. The begin and end methods of the ContextBuilder will delegate to the list of ContextInterceptors. Calling begin on a ContextBuilder will cause the invocation of the begin method on all its ContextInterceptors in the specified list sequence. The end method of the ContextBuilder will invoke all the end methods of its ContextInterceptors but in reverse order.
                  
                  Typical usage:
                  
                  List contextInterceptors = ...get a list of ContextInterceptor implementations...;
                  
                  ContextBuilder contextBuilder = new ContextBuilder(contextInterceptors);
                  try {
                   contextBuilder.begin();
                  
                   ... block of code ...
                  
                  } finally {
                   contextBuilder.end();
                  }
                  As you can see this is a do-it-yourself kind of AOP :)
                  
                  6.4. Thread context
                  In order for the ContextInterceptors to do something usefull, they must be able to make objects available to the block of code that is surrounded by the context builder. Since passing parameters is not a convenient option, the best alternative is using a ThreadLocal. More information on ThreadLocal can be found in the online javadocs.
                  
                  The jBPM class ThreadContext class adds some convenience to using ThreadLocals to support the interceptors in the context builder. Basically, ThreadContext is a thread local map. ThreadContext provides a set of static methods for the lookup and manipulation of the thread local entries.
                  
                  public abstract class ThreadContext {
                  
                   public static void put(String key, Object value) {...}
                   public static Object get(String key) {...}
                   public static Object remove(String key) {...}
                   ...
                  }
                  Each interceptor in a context builder can now use information from the thread context and produce information on the thread context. This is how we make the persistence, scheduling and messaging configurable: e.g. The first interceptor could lookup the hibernate session factory and put it in the thread context. The second interceptor takes the hibernate session factory, creates a hibernate session and puts that in the thread context. The third interceptor takes the hibernate session and creates the jbpm GraphSession, TaskMgmtSession, ... and so on.
                  
                  To see what interceptors we have and what they can do, look in the javadocs of the sub-packages of org.jbpm.tc..
                  
                  6.5. Object factory
                  The object factory can create objects according to a beans-like xml configuration file. The configuration file specifies how objects should be created, configured and wired together to form a complete object graph. The object factory can inject the configurations and other beans into a bean.
                  
                  In its simplest form, the object factory is able to create basic types and java beans from such a configuration:
                  
                  <beans>
                   <bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance"/>
                   <string name="greeting">hello world</string>
                   <int name="answer">42</int>
                   <boolean name="javaisold">true</boolean>
                   <float name="percentage">10.2</float>
                   <double name="salary">100000000.32</double>
                   <char name="java">j</char>
                   <null name="dusttodust" />
                  </beans>
                  
                  ---------------------------------------------------------
                  
                  ObjectFactory of = ObjectFactory.parseXmlFromAbove();
                  assertEquals(TaskInstance.class, of.getNewObject("task").getClass());
                  assertEquals("hello world", of.getNewObject("greeting"));
                  assertEquals(new Integer(42), of.getNewObject("answer"));
                  assertEquals(Boolean.TRUE, of.getNewObject("javaisold"));
                  assertEquals(new Float(10.2), of.getNewObject("percentage"));
                  assertEquals(new Double(100000000.32), of.getNewObject("salary"));
                  assertEquals(new Character('j'), of.getNewObject("java"));
                  assertNull(of.getNewObject("dusttodust"));
                  Also you can configure lists:
                  
                  <beans>
                   <list name="numbers">
                   <string>one</string>
                   <string>two</string>
                   <string>three</string>
                   </list>
                  </beans>
                  and maps
                  
                  <beans>
                   <map name="numbers">
                   <entry><key><int>1</int></key><value><string>one</string></value></entry>
                   <entry><key><int>2</int></key><value><string>two</string></value></entry>
                   <entry><key><int>3</int></key><value><string>three</string></value></entry>
                   </map>
                  </beans>
                  Beans can be configured with direct field injection and via property setters.
                  
                  <beans>
                   <bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
                   <field name="name"><string>do dishes</string></field>
                   <property name="actorId"><string>theotherguy</string></property>
                   </bean>
                  </beans>
                  Beans can be referenced. The referenced object doesn't have to be a bean, it can be a string, integer or any other object.
                  
                  <beans>
                   <bean name="a" class="org.jbpm.A" />
                   <ref name="b" bean="a" />
                  </beans>
                  Beans can be constructed with any constructor
                  
                  <beans>
                   <bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
                   <constructor>
                   <parameter class="java.lang.String">
                   <string>do dishes</string>
                   </parameter>
                   <parameter class="java.lang.String">
                   <string>theotherguy</string>
                   </parameter>
                   </constructor>
                   </bean>
                  </beans>
                  ... or with a factory method on a bean ...
                  
                  <beans>
                   <bean name="taskFactory"
                   class="org.jbpm.UnexistingTaskInstanceFactory"
                   singleton="true"/>
                  
                   <bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
                   <constructor factory="taskFactory" method="createTask" >
                   <parameter class="java.lang.String">
                   <string>do dishes</string>
                   </parameter>
                   <parameter class="java.lang.String">
                   <string>theotherguy</string>
                   </parameter>
                   </constructor>
                   </bean>
                  </beans>
                  ... or with a static factory method on a class ...
                  
                  <beans>
                   <bean name="task" class="org.jbpm.taskmgmt.exe.TaskInstance" >
                   <constructor factory-class="org.jbpm.UnexistingTaskInstanceFactory" method="createTask" >
                   <parameter class="java.lang.String">
                   <string>do dishes</string>
                   </parameter>
                   <parameter class="java.lang.String">
                   <string>theotherguy</string>
                   </parameter>
                   </constructor>
                   </bean>
                  </beans>
                  Each named object can be marked as singleton with the attribute singleton="true". That means that a given object factory will always return the same object for each request. Note that singletons are not shared between different object factories.
                  
                  The singleton feature causes the differentiation between the methods getObject and getNewObject. Typical users of the object factory will use the getNewObject. This means that first the object factory's object cache is cleared before the new object graph is constructed. During construction of the object graph, the non-singleton objects are stored in the object factory's object cache to allow for shared references to one object. The singleton object cache is different from the plain object cache. The singleton cache is never cleared, while the plain object cache is cleared at the start of every getNewObject method.
                  
                  An extension to the traditional beans schema is the context-builder tag. A context-builder element contains a list of ContextInterceptor objects. The singleton property is important here: thread safe ContextInterceptors can be marked as singleton, while context interceptors that maintain state in the member variables, must be created for each request. ContextBuilder's themselves should not be declared singleton since they have to maintain state (the index of the current executing context interceptor in case an exception occurs).



                  • 6. Re: Use Object Factory - Bean
                    pjmvn

                    No body help me ?

                    • 7. Re: Use Object Factory - Bean
                      koen.aers

                      Well, we sometimes *do* sleep here...
                      Anyway, I don't know how come that the problem with the chapter of Configuration is not showing up in the html folder of the 3.1alpha1 release docs (probably one or another build error), but it does show up in the html_single folder.
                      To answer your question, the object factory is meant to build configuration contexts. For an example of it, you should look at the jbpm.cfg.xml file. That is the place where these configurations are read. There is no GPD support for it as it has nothing to do with designing processes. You should stay tuned because this mechanism is evolving a lot and will look different again for the next alpha release.

                      Regards,
                      Koen

                      • 8. Re: Use Object Factory - Bean
                        pjmvn

                        Thanks for reply.
                        I am interested costomize objects.
                        I see Object Factory can do it for me, but i am very new in this, so you can interpret more about it for me.
                        Ex:
                        * We can create customize object and use it in our jBPM project ? (how to use)
                        * We can save that object to database of jBPM, translate it from this node to other node ?
                        * We can read our object in WebApp from database or jBPM environment ?
                        * And more .....

                        And thank you very much.