Search code examples
javaspringannotationsactivitiapplicationcontext

Annotation based Spring Activiti ProcessEngine


I am quite new to Spring and Activiti. I'm developing annotation based Spring web application with embedded Activiti engine. I have some services implemented, SubscriptionService is one of them. In one process I call that service as bean with:

activiti:expression="${subscriptionService.getContacts(publisherCode, contactType)}"

Service:

@Service
@Transactional
public class DBSubscriptionService implements SubscriptionService {
...
}

I have separated test module and web module. Test module loads context from activiti.cfg.xml with

@ContextConfiguration("classpath:activiti.cfg.xml")

and it is:

<bean id="processEngineConfiguration"
    class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
    <property name="databaseType" value="h2" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="jobExecutorActivate" value="false" />
    <property name="history" value="full" />
    <property name="mailServerPort" value="2025" />
</bean>

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>

<bean id="repositoryService" factory-bean="processEngine"
    factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine"
    factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine"
    factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine"
    factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine"
    factory-method="getManagementService" />
<bean id="identityService" factory-bean="processEngine"
    factory-method="getIdentityService" />
<bean id="formService" factory-bean="processEngine"
    factory-method="getFormService" />

<context:component-scan base-package="cz.muni.fi.cep" />
<context:annotation-config />

In test module, everything works fine. But in web module when it should call subscriptionService Bean it throws:

    Unknown property used in expression: ${subscriptionService.getContacts(publisherCode, contactType)}
Caused by: org.activiti.engine.impl.javax.el.PropertyNotFoundException: Cannot resolve identifier 'subscriptionService'
    at org.activiti.engine.impl.juel.AstIdentifier.eval(AstIdentifier.java:83)
    at org.activiti.engine.impl.juel.AstMethod.invoke(AstMethod.java:79)
    at org.activiti.engine.impl.juel.AstMethod.eval(AstMethod.java:75)
    at org.activiti.engine.impl.juel.AstEval.eval(AstEval.java:50)
    at org.activiti.engine.impl.juel.AstNode.getValue(AstNode.java:26)
    at org.activiti.engine.impl.juel.TreeValueExpression.getValue(TreeValueExpression.java:114)
    at org.activiti.engine.impl.delegate.ExpressionGetInvocation.invoke(ExpressionGetInvocation.java:33)
    at org.activiti.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:37)
    at org.activiti.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:25)
    at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:48)
    ... 363 more

So I understand problem is that Process engine does not use right application context, because subscription service is autowired to other classes just fine. But I don't know how to fix it.

Web module is purely annotation based:

@EnableAutoConfiguration
@Configuration
@EntityScan(basePackages = "cz.muni.fi.cep")
@ComponentScan(basePackages = "cz.muni.fi.cep")
public class App extends WebMvcConfigurerAdapter {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    ...
} 

And Activiti configuration:

@Configuration
public class ActivitiConfig {

    @Bean
    public ProcessEngine processEngine(ProcessEngineConfigurationImpl pec, ApplicationContext applicationContext) throws Exception {
        ProcessEngineFactoryBean pe = new ProcessEngineFactoryBean();
        pe.setProcessEngineConfiguration(pec);
        pe.setApplicationContext(applicationContext);

        return pe.getObject();
    }

    @Bean
    public ProcessEngineConfigurationImpl getProcessEngineConfiguration(
            DataSource dataSource,
            PlatformTransactionManager transactionManager,
            ApplicationContext context) {
        SpringProcessEngineConfiguration pec = new SpringProcessEngineConfiguration();

        pec.setDataSource(dataSource);
        pec.setDatabaseSchemaUpdate("true");
        pec.setJobExecutorActivate(true);
        pec.setHistory("full");
        pec.setMailServerPort(2025);
        pec.setDatabaseType("mysql");

        pec.setTransactionManager(transactionManager);
        pec.setApplicationContext(context);

        return pec;
    }

    @Bean
    public RuntimeService getRuntimeService(ProcessEngine processEngine) {
        return processEngine.getRuntimeService();
    }
...
}

Also, maybe order of context creation has somethong to do with this.


Solution

  • Everything looks OK, I believe it might be something as simple as the subscription service not being scanned (does it belong to package cz.muni.fi.cep?), or Spring assigning another name to the subscription service bean (i.e. dbSubscriptionService or dBSubscriptionService instead of just subscriptionService).

    Try replacing @Service in DBSubscriptionService class by @Service("subscriptionService") and it should work.