Announcement Announcement Module
Collapse

Spring Modules forum decommissioned in favor of Spring Extensions

As the Spring Modules project has been replaced by the Spring Extensions (http://www.springsource.org/extensions) project, this forum has been decommissioned in favour of Spring Extensions one at:
http://forum.springsource.org/forumdisplay.php?f=44

Please see the Spring Extensions home page for a complete list of current projects in Java, .NET and ActionScript. You can also propose one if you want.

Cheers,
Costin Leau
SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
http://twitter.com/costinl
See more
See less
jBPM ActionHandler and Spring Module Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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).

    Comment


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

      Juergen

      Comment


      • #4
        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).

        Comment


        • #5
          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.

          Comment


          • #6
            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

            Comment


            • #7
              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!

              Comment


              • #8
                See this thread for a follow-up.

                Comment

                Working...
                X