cancel
Showing results for 
Search instead for 
Did you mean: 

Using spring @Autowire in ExecutionListener not working

davidwaf
Champ in-the-making
Champ in-the-making
Hi all,
I have a web app, that among other things, is using Activiti  for BPM. What i did is dropped these into the classpath:
activiti-engine-5.6.jar
activiti-spring-5.6.jar

Then, my spring-activi config is as follows
[size=85]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

   
   <!– Use annotations to configure our components –>
    <context:component-scan base-package="org.activiti" />

   <!– Turn on annotations for beans –>
    <context:annotation-config />

   <!– Configure datasource –>
    <bean id="dataSource" lazy-init="false"
      class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
        <property name="targetDataSource">
            <bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
                <property name="driverClass" value="com.mysql.jdbc.Driver" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </bean>
        </property>
    </bean>

   <!– Configure transaction manager –>
    <bean id="transactionManager" lazy-init="false"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

   <!– Use transaction manager annotations –>
    <tx:annotation-driven transaction-manager="transactionManager" />

   <!– Configure process engine –>
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"
      lazy-init="true">
        <property name="databaseType" value="mysql" />
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="databaseSchemaUpdate" value="true" />
        <property name="jobExecutorActivate" value="false" />
    </bean>

   <!– Use process engine –>
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"
      lazy-init="true">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

   <!– Use process engine service –>
    <bean id="repositoryService" factory-bean="processEngine"
      factory-method="getRepositoryService" lazy-init="true" />
    <bean id="runtimeService" factory-bean="processEngine"
      factory-method="getRuntimeService" lazy-init="true" />
    <bean id="taskService" factory-bean="processEngine"
      factory-method="getTaskService" lazy-init="true" />
    <bean id="historyService" factory-bean="processEngine"
      factory-method="getHistoryService" lazy-init="true" />
    <bean id="managementService" factory-bean="processEngine"
      factory-method="getManagementService" lazy-init="true" />
    <bean id="identityService" factory-bean="processEngine"
      factory-method="getIdentityService" lazy-init="true" />
    <bean id="formService" factory-bean="processEngine"
      factory-method="getFormService" lazy-init="true" />
               
    <bean id="propertyService" class="org.licosystems.web.lico.config.properties.PropertyServiceImpl"/>
    <bean id="mailService" class="org.licosystems.web.lico.util.MailService"/>
  

</beans>
[/size]

Now the above configuration allows me to inject the beans perfectly in Controllers anywhere in the app…and i use them, no problem. Now the last two beans: propertyService and mailService are meant to be used in ExecutionListener below:

[size=85]
public class ProcessStartListener implements ExecutionListener {

    private PropertyService propertyService;
    private MailService mailService;
    private FormService formService;

    @Autowired
    public void setFormService(FormService formService) {
        this.formService = formService;
    }

    @Autowired
    public void setMailService(MailService mailService) {
        this.mailService = mailService;
    }

    @Autowired
    public void setPropertyService(PropertyService propertyService) {
        this.propertyService = propertyService;
        System.out.println(" &&&&&&&&&&& PRoperty auto wiered: " + this.propertyService);
    }

    @Override
    public void notify(DelegateExecution execution) throws Exception {

    }
}
[/size]


But nope, it is not happening. No Autowiring. Is bean injection possible in ExecutionListeners ? Any step i could be missing?
Thanks
6 REPLIES 6

davidwaf
Champ in-the-making
Champ in-the-making
Ok, i abandoned the whole idea of autowiring directly in ExecutionListener, opted to use field injection, which gives me access to the beans. And that works fine.

divakar
Champ in-the-making
Champ in-the-making
HI David,

Can you give me the sample expression for field injection for the above scenarios stated, so that we are able to access mailService, propertyService beans in the notify method.

I have a web application, that uses annotations for defining beans. When i tried to use an AutoWired bean in an ExecutionListener, i get only Null reference. Process Definition and Code of the ExecutionListener is given below

Excerpt from Process definition BPMN file
———————————–
<sequenceFlow id="toFinanceReview" name="Goes To Finance Review" sourceRef="exclusivegateway1" targetRef="financeReview">
      <extensionElements>
        <activiti:executionListener event="take" class="edu.divakar.handlers.EmailListener"></activiti:executionListener>
      </extensionElements>
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${managerDecision == 'approve'}]]></conditionExpression>
    </sequenceFlow>
===============================================================================


public class EmailListener implements ExecutionListener {

    @Autowired
    EmailService emailService;

    @Override
    public void notify(DelegateExecution arg0) throws Exception {
        Map<String, Object> processVariableMap = arg0.getVariables();
        emailService.sendEmail(processVariableMap); //HERE I GET ONLY NULL
    }
}

Thanks in advance.

jbarrez
Star Contributor
Star Contributor
That original post is from 2011 …

Anyway.

class="edu.divakar.handlers.EmailListener"> is NOT a spring bean. @Autowired is never going to work on a non-spring bean. Your emailListener needs to be a Spring bean too to make it work.

divakar
Champ in-the-making
Champ in-the-making
Hi Joram,

Activiti is awesome and great to receive an reply from you.

I am new to Spring. I have annotated the above EmailListener class with @Component and defined a method in my config class as follows
@Bean
    public EmailListener getEmailListener() {
        return new EmailListener();
    }

Now, my question is, to make activiti take this spring bean, how should i define it in the process definition. I tried the following but none worked.

<activiti:executionListener event="take" class="${emailListener}"></activiti:executionListener>
<activiti:executionListener event="take" class="#{emailListener}"></activiti:executionListener>
<activiti:executionListener event="take" expression="${emailListener}"></activiti:executionListener>
<activiti:executionListener event="take" expression="#{emailListener}"></activiti:executionListener>

I guess i am missing something silly. Please bear with me and give me the solution. Thanks.

trademak
Star Contributor
Star Contributor
Hi,

It can only work with an expression or delegateExpression attribute. But the expression attribute should also contain the method you want to invoke. So something like ${emailListener.notify(execution)}

Best regards,

divakar
Champ in-the-making
Champ in-the-making
Hi Thanks. Actually my problem was activiti was using a different context, which was not having the emailListener bean. However once i set the application context in my SpringProcessEngineConfiguration and in ProcessEngineFactoryBean, it worked fine.

Thanks for the help too.