Spring beans not injected into Flowable context

Hello, I’m trying to add Flowable into my project and I’m facing an issue when my Spring beans are not automatically added into Flowable context, therefore I cannot call them from by processes. From documentation and tests I understood this should work out of the box. Could you please advise if I’m doing something wrong / missing some configuration?
I’m using Flowable 6.3.1 and Spring Boot 2.0.2.

Flowable dependencies Pom:

        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter-rest</artifactId>
            <version>${flowable.version}</version>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-http</artifactId>
            <version>${flowable.version}</version>
        </dependency>

My custom configuration class:

@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
	@Override
	public void configure(SpringProcessEngineConfiguration config) {
             // custom form types here...
        }
}

Example of interface and bean, that does not get picked up by Flowable:

public interface PropertyService {
	String getValue(String property);
}

@Slf4j
@Component("propertyService")
public class PropertyServiceImpl implements PropertyService {

	private final Environment environment;

	@Autowired
	public PropertyServiceImpl(Environment environment) {
		this.environment = environment;
	}

	@Override
	public String getValue(String property) {
		String value = environment.getProperty(property);
		return value == null ? null : value.trim();
	}
}

This way I’d expect propertyService to be available in process expressions and script tasks (I’m using Groovy), however I’m always getting exception on missing property or bean.

Thanks for your time!

Hi,

Make sure that the package where you implemented the PropertyService is component scanned by Spring. Or you can create a @Bean method in the FlowableConfig class you created for example.

Best regards,

Tijs

Hi Tijs,

Thanks for your reply. The package is component scanned, I’ve also tried creating the service using @Bean factory as you suggested and the property service is still not accessible in the process…
The bean is 100% created as I can autowire it anywhere else and is also returned by Actuator in bean listing.

Is there any other catch or configuration I’m missing?

Thanks a lot! Kind Regards,
Jan

Hi, Did you ever get an answer to this question? I’m trying to do the same thing, and my beans are always null inside the JavaDelegate. tia, adym

Hi, didn’t make it work out of the box. My hacky solution was a bean post processor scanning all beans from certain packages and manually adding these to engine context.

Hi, I did get this to work, but I HAD to declare the beans within the Process Engine Configuration XML Element :

<bean 
    id="beanApproveTransaction" 
    class="com.lmig.ci.billing.tasks.ApproveTransaction">
    <property name="emailService" ref="emailService"/>
</bean>

<bean 
    id="beanEmailTask" 
    class="com.lmig.ci.billing.tasks.EmailTask">
    <property name="emailService" ref="emailService"/>
</bean>

<bean id="processEngineConfiguration"
    class="org.flowable.spring.SpringProcessEngineConfiguration">

    <property   name="dataSource"               ref="dataSource" />
    <property   name="transactionManager"       ref="transactionManager" />
    <property   name="databaseSchemaUpdate"     value="true" />
    <property   name="asyncExecutorActivate"    value="false" />

    <!-- 
    <property   name="deploymentResources"      value="classpath*:/xml/*.bpmn20.xml" />
     -->

    <property name="mailServerHost"             value="smtpin.lmig.com" />
    <property name="mailServerPort"             value="25" />

    <!--
    BEANS : Spring Beans integrated with the Flowable Engine 
            <entry key="beanEmailService"       value-ref="emailService" />
    -->
    <property name="beans">
        <map>
            <entry key="beanApproveTransaction" value-ref="beanApproveTransaction" />
            <entry key="beanEmailTask"          value-ref="beanEmailTask" />
        </map>
    </property>
</bean>

hth,

adym

Hello,

The same for me.
Impossible to retrieve Flowable beans (ProcessEngine, TaskService…) in my JavaDelegate class (declared as @Service) called by a Service Task.
For example, @Autowired TaskService defined in my Spring configuration file (declared as @Configuration) returns a TaskService object when it returns null in the JavaDelegate.
And no way to find an example on the Flowable forum or anywhere else on the net. :frowning:
Remark: I use flowable embedded in a spring boot application.

Thanks for your help
Best Regards
William

1 Like

Hello, I have the same issue. Is there an annotations based work-around for this?
I’d really like to inject the resource that the delegate needs rather than some other hack.
Thanks,
Eric

Here is the work-around I found in a related post somewhere…

Define the beans in the application class

@SpringBootApplication
public class DeckServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeckServiceApplication.class, args);
    }
    @Bean
    public MotionServerClient getMotionServerClient(@Value("${devices.motion.host}") String host, @Value("${devices.motion.port}") int port) {
        MotionServerClient motionServerClient = new MotionServerClient(host, port);
        return motionServerClient;
    }
    @Bean
    public BarcodeServerClient getBarcodeServerClient(@Value("${devices.barcode.host}") String host, @Value("${devices.barcode.port}") int port) {
        BarcodeServerClient barcodeServerClient = new BarcodeServerClient(host, port);
        return barcodeServerClient;
    }
}

Create an initializer component that saves the beans to a static utility using a @PostConstruct method

@Component
public final class DeviceClientFactoryInitializer {
    @Autowired
    private MotionServerClient motionServerClient;
    @Autowired
    private BarcodeServerClient barcodeServerClient;
    @PostConstruct
    public void init() {
        DeviceClientUtil.setMotionServerClient(motionServerClient);
        DeviceClientUtil.setBarcodeServerClient(barcodeServerClient);
    }
}

Access the beans in the Flowable referenced listeners or executions using the static utility methods

public class DeviceClientUtil {
    private static MotionServerClient motionServerClient;
    private static BarcodeServerClient barcodeServerClient;
    
    private DeviceClientUtil() {}

    public static MotionServerClient getMotionServerClient() {
        return motionServerClient;
    }
    public static BarcodeServerClient getBarcodeServerClient() {
        return barcodeServerClient;
    }
    public static void setMotionServerClient(MotionServerClient client) {
        DeviceClientUtil.motionServerClient = client;
    }
    public static void setBarcodeServerClient(BarcodeServerClient client) {
        DeviceClientUtil.barcodeServerClient = client;
    }
}
private ManagementService getManagementService() {
    return (ManagementService) AppContext.getApplicationContext().getBean(ManagementService.class);
}

If the bean is a singleton, you can make the field static and inject it in the usual way.

I know this thread is a little old, but for the benefit of those who sailed into here via Google and have similar issue, here the solution that worked for me. If you want your service delegate to be Spring managed and injected into the workflow, you can do the following steps:

  1. Create service delegate bean in Spring:

@Component
public class JavaSpringManagedDelegate implements JavaDelegate {

@Override
public void execute(DelegateExecution execution) {

  //delegate code

}

}

Through the magic of component scanning and naming convention, Spring will create a bean named “javaSpringManagedDelegate”.

  1. This bean instance can be used in Java service activity by setting the delegateExpression attribute to “${javaSpringManagedDelegate”, i.e. use the field named Delegate Expression: in the modeler.

When flowable executes this activity, it will pull this bean from Spring’s application context and call the execute method.

2 Likes

@jwashington can you please elaborate last step a little on how to use the javaSpringManagedDelegate bean to solve the current issue

This also worked for me.

Once I loaded the bean that was implementing JavaDelegate into my application context, I was able to access it from flowable and even load other autowired beans in the same class (which were previously since the java delegate was not spring aware once it came out of the process engine).

The issue raised in this thread was how to Spring inject flowable objects (RuntimeService, etc.) into a JavaDelegate that is called by the workflow. The solution I proposed creates a JavaDelegate as a Spring component which can be referenced from the modeler using the delegateExpression attribute as the bean name (in the example the name of the bean is javaSpringManagedDelegate via the Spring naming conventions). Since the delegate is managed by Spring, it is easy to inject other Flowable Spring objects such as the runtimeService, repositoryService, etc through the usual Spring mechanisms such as autowiring or constructor injection.