Results 1 to 8 of 8

Thread: jBPM ActionHandler and Spring Module

  1. #1
    Join Date
    Jan 2005
    Location
    Austin, TX
    Posts
    9

    Default jBPM ActionHandler and Spring Module

    I checked out the jbpm spring module classes from cvs and imported them into a project i'm working on. I'm curious how/if anyone has devised a strategy to load spring beans inside of an ActionHandler implementation.

    Has anyone cooked up a Support subclass where a reference is obtained from a existing application context?

    -b

  2. #2
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Check the forums - I think the project 'might' have moved into the Spring CVS under spring-projects folder (I'm not sure about this myself that's why you should check for yourself).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  3. #3
    Join Date
    Nov 2005
    Location
    Austria
    Posts
    38

    Default

    Currently working on it. Anyone else, too? Why isn't there any progress in the spring-projects JBPM?

    Juergen

  4. #4
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    AFAIK, Rob (Harrop) has done most of the work and with 1.3 release around the corner, the Spring Experience conference happening in States and Javapolis in Belgium I assume he doesn't have much time left. I'm just guessing - try the mailing list (Spring Modules or Spring dev).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  5. #5
    Join Date
    Nov 2004
    Location
    Dallas, TX USA
    Posts
    24

    Arrow

    Costin, I've tried contacting Rob about this, you're assumption is correct, he must be very busy. Therefore, I've moved along making my own changes in hopes Rob might be able to use them later.

    Anyway, I've been using spiring-jbpm for 2 months now. Rob Harrop is maintains the current spring-jbpm code in the spring-projects section of the official springframework repository. I'll have to warn you, there is some bugs related to hibernate transactions. Two issues have been logged regarding the known bugs MOD-52
    MOD-58
    Patching spring-jbpm with the code from MOD-58 is pretty much required to get sping-jbpm to run.

    OK - l have a solution in place to provide Spring dependency injection to ActionHandlers and AssignmentHandlers. The solution uses a simple proxy technique similiar to proxying Struts actions through Spring. I did it using 2 classes ActionHandlerProxy implementing ActionHandler and AssignmentHandlerProxy implementing AssignmentHandler. As with the Struts proxy technique, you use the proxy class in your JBPM process definition in place of the actual handler class. The catch is, you have to declarativley set one property the proxy class knows about in order to pull the handler class from Spring beanfactory.

    This how the configuration in process definition will look
    Code:
    	<node name="check and spawn">		
    		<transition to="end top level request"></transition>
    		<event type="node-enter">
    			<action config-type="bean" class="my.package.ActionHandlerProxy">
    			<handlerBean>checkAndCreate</handlerBean>
    			</action>
    		</event>
    	</node>
    Since the ActionHandlerProxy is an implementation of ActionHandler, JBPM calls the execute method which in turn pulls the bean with id checkAndCreate from the beanfactory and run's it's execute() method. This does mean that you must have some way to give your proxy a refrence to the Spring beanfactory (ApplicationContext in this case). To do that, both the handler proxy clases have a base class with a static variable referencing the Spring AppContext/BeanFactory. The only thing I don't like about it is I had to use the static refrence.

    Here's code for the proxies.
    Code:
    public  class JbpmHandlerProxy implements ApplicationContextAware, InitializingBean {
        
        private String handlerContextLocation;
        
        //Very important that the handlerBean value be set in the JBPM process Definition
        //this tells the proxy exactly which bean to run
        public String handlerBean;
        
        //All subclasses are expected to set the handler interface
        protected Class handlerInterface;
        
        
        private static ApplicationContext handlerContext;
        
        public void afterPropertiesSet() throws Exception {
            
            try {
                getHandlerContext();
            } catch (Exception e) {
                throw new BeanCreationException("The jBPM handler context could not be configured ", e );
            }
            onLoad();     
        }
    
           public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            handlerContext = new ClassPathXmlApplicationContext(new String[]{handlerContextLocation},applicationContext);
            
        }
        
        private ApplicationContext getHandlerContext()
        {
            if (handlerContext == null) {
                throw new IllegalStateException(
                        "ApplicationContext owned for the jBPM handlers is now null");
            }
            return handlerContext;
            
        }
    
        /**
         * For use in subclasses.  Returns the actual handler object from Spring
         * @return
         * 
         * @throws HandlerProxyException an unchecked exception if the bean is not found or the specified class does not match
         */
        protected Object getHandlerBean() {
            Object beanObject = getHandlerContext().getBean(handlerBean);
            if(beanObject == null)
                throw new HandlerProxyException("The jBPM Handler proxy could not find the corresponding ActionHandler " +
                        "in spring's ApplicationContext, make sure the handlerBean with name"+handlerBean+" exists in the ApplicationContext");
            
            if( ! (handlerInterface.isAssignableFrom(beanObject.getClass())))
                throw new HandlerProxyException("The jBPM Handler retrieved from Spring is of type ["+beanObject.getClass().getName()+"] but " +
                        "exepecting ["+handlerInterface+"]");
            return beanObject;
        }
    
        public void setHandlerContextLocation(String handlerContextLocation) {
            this.handlerContextLocation = handlerContextLocation;
        }
    
     
        /**
         * Designed for the sub classes to use for executing code on startup
         */
        protected void onLoad() throws Exception
        {
            //blank - implemented by subclass
        }
    }
    
    public class ActionHandlerProxy extends JbpmHandlerProxy implements ActionHandler {
        
        
        private static final long serialVersionUID = 1L;    
    
        public void execute(ExecutionContext executionContext) throws Exception {
    
            handlerInterface = ActionHandler.class;
    
            ActionHandler actionHandler  = (ActionHandler)getHandlerBean();
            actionHandler.execute(executionContext);
    
        }   
        
        /**
         * @param handlerBean The handlerBean to set.
         */
        public void setHandlerBean(String handlerBean) {
            this.handlerBean = handlerBean;
        }
    }
    
    public class AssignmentHandlerProxy extends JbpmHandlerProxy implements AssignmentHandler {
    
     
        private static final long serialVersionUID = 1L;
    
        public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception {
            handlerInterface = AssignmentHandler.class;
            
            AssignmentHandler handler = (AssignmentHandler)getHandlerBean();
            
            handler.assign(assignable, executionContext);
    
        }
        
        /**
         * @param handlerBean The handlerBean to set.
         */
        public void setHandlerBean(String handlerBean) {
            this.handlerBean = handlerBean;
        }
    
    }
    Eventually, I'd like to get this code, or code like it, into the spring-jbpm source repo.
    -steve

  6. #6
    Join Date
    Nov 2005
    Location
    Austria
    Posts
    38

    Default

    Hi Steve!

    Thanks for the sample. I don't like the static reference to the application context. Do you think your code is thread-safe? Do you think it can be used in an EJB Container?
    Maybe using the strategy of SLSBs with ContextSingletonBeanFactoryLocator would be better.

    Juergen
    _________________________________
    Juergen Mayrbaeurl - Solution architect

  7. #7
    Join Date
    Nov 2004
    Location
    Dallas, TX USA
    Posts
    24

    Default

    Your're right, I need to re-work this using the BeanFactoryLocator as a delegate. I'd use the BeanFactoryRefrence to hold a reference to the ApplicationContext. I should be able to put that together rather quickly.

    Thanks for the input!
    -steve

  8. #8
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    See this thread for a follow-up.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •