cancel
Showing results for 
Search instead for 
Did you mean: 

Proper way to implement a custom a taskListener in Activiti?

jpotts
World-Class Innovator
World-Class Innovator
I want to implement a custom taskListener that leverages the ActionService. I have written a Java class that implements TaskListener. The problem I'm having is how to properly inject the dependency and how to refer to the taskListener from the process definition.

I tried creating the following in one of my context files:
<bean id="externalReviewNotification" class="com.someco.bpm.ExternalReviewNotification">
        <property name="actionService">
            <ref bean="ActionService" />
        </property>
</bean>

I've also tried a version that includes "parent="baseJavaDelegate"".

I then refer to the bean from my process using delegateExpression, like this:
<activiti:taskListener event="create" delegateExpression="${externalReviewNotification}"></activiti:taskListener>

That fails with a org.activiti.engine.ActivitiException: Exception while invoking TaskListener: Unknown property used in expression

I think it is because my bean isn't registered with the activiti bean registry, but I'm not sure.

I've tried using a class attribute instead of the delegateExpression attribute. In that case, notify is called, but my dependencies aren't loaded since it isn't using the bean.

I looked at the source to see how the JavaScript taskListener works. It has a getServiceRegistry method. I suppose I could implement that, but I'm wondering if there's a better way?

Jeff
21 REPLIES 21

michalwrobel
Champ on-the-rise
Champ on-the-rise
Hi,

I tried to implement similar thing as you, but using Activiti ServiceTask, and had the same problems as you.

'activiti:class' way worked fine, and delegateExpression had not. I've also implemented my own class which registered in activitiBeanRegistry, without utilizing baseJavaDelegate bean.

The only way I've found to evade this problem was to manually register my bean in activiti-context.xml by adding new entry to activitiBeanRegistry map:

<util:map id="activitiBeanRegistry" map-class="java.util.HashMap">
        <entry key="services" value-ref="ServiceRegistry" />
    <entry key="simpleLoggerServiceTask" value-ref="simpleLoggerServiceTask" />
       
    </util:map>

Just like classes utilising activitiBeanRegistry couldn't reach runtime updates in this map..

The important thing is that both key and value-ref have to have the same value - id of the bean.

I see you have released workflow tutorial yesterday and just scrolled through it, but haven't found there utilising java classes in workflows the way we are talking here about.
Have you figured out how to do it, or have you given up for the moment?
Or is this issue now officially bug?

jpotts
World-Class Innovator
World-Class Innovator
In the tutorial I use a taskListener that refers to the class by name:
<activiti:taskListener event="create" class="com.someco.bpm.ExternalReviewNotification"></activiti:taskListener>

And then within the class I have a getServiceRegistry method that I stole from ActivitiScriptBase.java. It retrieves the service registry so I can have access to Alfresco's services:
protected ServiceRegistry getServiceRegistry() {
        ProcessEngineConfigurationImpl config = Context.getProcessEngineConfiguration();
        if (config != null) {
            // Fetch the registry that is injected in the activiti spring-configuration
            ServiceRegistry registry = (ServiceRegistry) config.getBeans().get(ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY);
            if (registry == null) {
                throw new RuntimeException(
                            "Service-registry not present in ProcessEngineConfiguration beans, expected ServiceRegistry with key" +
                            ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY);
            }
            return registry;
        }
        throw new IllegalStateException("No ProcessEngineCOnfiguration found in active context");
    }   

Jeff

dmralfing
Champ in-the-making
Champ in-the-making
Sorry Jeff, but I´m afraid I didn´t understand the solution you suggested due to I´m a beginner in activity.
Please, may you tell me what I'm doing wrong in this code or else what´s the best way to get
the service registry having Alfresco 4.2.x?
This is my wf:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="Examples">
  <process id="MyTest" name="MyTest">
   <startEvent id="theStart" name="Start">
   </startEvent>
    <serviceTask id="javaService" name="Java service invocation" activiti:class="org.activiti.examples.bpmn.test.manager2.SetterTest">
      <extensionElements>
        <activiti:field name="text">
          <activiti:string>Success</activiti:string>
        </activiti:field>
        <activiti:taskListener event="create" class="org.activiti.examples.bpmn.test.manager2.SetterTest">
        </activiti:taskListener>
      </extensionElements>
    </serviceTask>
   <userTask id="usertask1" name="User Task" activiti:candidateGroups="user"></userTask>
   
   <endEvent id="theEnd" name="End"></endEvent>
    <sequenceFlow id="flow1" name="" sourceRef="theStart" targetRef="javaService"></sequenceFlow>
    <sequenceFlow id="flow2" name="" sourceRef="javaService" targetRef="usertask1"></sequenceFlow>   
    <sequenceFlow id="flow4" name="" sourceRef="usertask1" targetRef="theEnd"></sequenceFlow>
  </process>
</definitions>


..and this is my class that unaffortunately doesn´t get the serviceRegistry..

package org.activiti.examples.bpmn.test.manager2;
import …
……….
public class SetterTest implements JavaDelegate {

   private static final String VARIABLE_NAME = "testVariable";
   private Expression text;
   ServiceRegistry serviceRegistry=null;
   //public ServiceRegistry getServiceRegistry() {return serviceRegistry;}
   protected ServiceRegistry getServiceRegistry() {

        ProcessEngineConfigurationImpl config = Context.getProcessEngineConfiguration();
        if (config != null) {
            ServiceRegistry registry = (ServiceRegistry) config.getBeans().get(ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY);
            if (registry == null) {
                throw new RuntimeException(
                            "Service-registry not present in ProcessEngineConfiguration beans, expected ServiceRegistry with key" +
                            ActivitiConstants.SERVICE_REGISTRY_BEAN_KEY);
            }
            else
               System.out.println("————— config =null");
            return registry;
        }

        throw new IllegalStateException("No ProcessEngineCOnfiguration found in active context");

    }   
   public void setServiceRegistry(ServiceRegistry serviceRegistry) {this.serviceRegistry = serviceRegistry;}
   public void execute(DelegateExecution execution)
   {
         if (serviceRegistry==null)
            System.out.println("serviceRegistry is null!!");
   }
}

Thank you so much!

amandaluniz_z
Champ on-the-rise
Champ on-the-rise
I faced the same problem and found the same work around (register the bean manually overriding the activitiBeanRegistry).

This is not the best solution as if you have more than one module, and want to register beans within the AMP file not in shared/classes/alfresco/extension… There'll be a workflow that won't work.

I've already raised a ticket with Alfresco Support, fingers crossed they fix that!

Regards,
Adei

amandaluniz_z
Champ on-the-rise
Champ on-the-rise
Alfresco engineers have come back to me in this matter.

According to them, it's not the spring bean id the one we need to put in the delegateExpression property but the base name of the java class (for Jeff's example if would be ExternalReviewNotification)

pero
Champ in-the-making
Champ in-the-making
According to them, it's not the spring bean id the one we need to put in the delegateExpression property but the base name of the java class (for Jeff's example if would be ExternalReviewNotification)

So has anyone else tried this solution? I've tried it and it still doesn't work.

amandaluniz_z
Champ on-the-rise
Champ on-the-rise
I haven't tried it, to be honest.

The previous one, overriding the bean, works.

Adei

pero
Champ in-the-making
Champ in-the-making
I faced the same problem and found the same work around (register the bean manually overriding the activitiBeanRegistry).

This is not the best solution as if you have more than one module, and want to register beans within the AMP file not in shared/classes/alfresco/extension… There'll be a workflow that won't work.

I've already raised a ticket with Alfresco Support, fingers crossed they fix that!

Regards,
Adei

Could you post a link to that Jira ticket so we can vote on it?

amandaluniz_z
Champ on-the-rise
Champ on-the-rise
Sorry, didn't create a JIRA ticket, I meant an Alfresco Support ticket
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.