Database connection from a TaskListener

Hello all!

Is there any way to obtain a database connection from a TaskListener instance (flowable 6.2)?

You can get the current connection via an internal class: org.flowable.engine.impl.util.CommandContextUtil.getDbSqlSession()…getSqlSession().getConnection()

However, that is very low-level … what’s the use case you’re trying to solve?

Good evening, Joram!

Thank you for your answer! You answer is exactly I’ve looked for.
And I’m sorry for delay with my answer.

I suppose write some aditional information each time after some human-task have been executed.

I’m trying to imagine where a listener should obtain a database connection from.
It’s seems logical for me that I can obtain connection from the same source as the engine.
Your example code doesn’t seems too low-level for me but, in such case, only embarrassing me thing is transaction management.

I don’t know what is a right approach in this context.
Should I use third-party (in sense independence from the Flowable core classes) connection prowider may be?

I think you could also use a custom mapping with other tables created in flowable schema.


This is a example:

Create new table in your flowable schema:

CREATE TABLE `per_salary` (
  `name` varchar(45) DEFAULT NULL,
  `pay` float DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)

And add some rows…

Create a custom mapper connection: custom-mybatis-mappers-flowable.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns=""

  <bean id="processEngineConfiguration"

    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/flowableTest" />
    <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUsername" value="example" />
    <property name="jdbcPassword" value="example" />

    <!-- job executor configurations -->
    <property name="asyncExecutorActivate" value="false" />
    <property name="databaseSchemaUpdate" value="true" />
    <!-- The custom mybatis mappers -->
    <property name="customMybatisMappers">

Create your mapper: customSalaryMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> 

<!DOCTYPE mapper PUBLIC "-// Mapper 3.0//EN" "">

<mapper namespace="com.fegor.flowable.SalaryMapper">
  <resultMap id="customSalaryResultMap" type="com.fegor.flowable.mapper.Salary">
    <id property="id" column="ID" jdbcType="INTEGER"/>
    <result property="name" column="NAME" jdbcType="VARCHAR"/>
    <result property="pay" column="PAY" jdbcType="FLOAT"/>

  <sql id="selectCustomSalaryColumns">
	<select id="selectCustomSalaryList" parameterType="string" resultMap="customSalaryResultMap">
		select <include refid="selectCustomSalaryColumns"/> from PER_SALARY PER

Create a entity:

package com.fegor.flowable.mapper;

public class Salary {

	protected int id;
	protected String name;
	protected float pay;
	public int getId() {
		return id;
	public void setId(int id) { = id;
	public String getName() {
		return name;
	public void setName(String name) { = name;
	public float getPay() {
		return pay;
	public void setPay(float pay) { = pay;

Create file for test mapper:

package com.fegor.flowable.test.mapper;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Select;

public interface MyTestMapper {
    @Select("SELECT ID as id, NAME as name, PAY as pay FROM PER_SALARY")
    List<Map<String, Object>> selectSalaries();

And create your test file:

package com.fegor.flowable.test.mapper;

import java.util.List;
import java.util.Map;

import org.flowable.engine.common.impl.cmd.CustomSqlExecution;
import org.flowable.engine.impl.cmd.AbstractCustomSqlExecution;
import org.flowable.engine.impl.test.ResourceFlowableTestCase;

public class MapperSalaryTest extends ResourceFlowableTestCase {

    public MapperSalaryTest() {

    public void testSelectSalaryColumns() {
        CustomSqlExecution<MyTestMapper, List<Map<String, Object>>> customSqlExecution = new AbstractCustomSqlExecution<MyTestMapper, List<Map<String, Object>>>(MyTestMapper.class) {

        	public List<Map<String, Object>> execute(MyTestMapper customMapper) {
                return customMapper.selectSalaries();

        List<Map<String, Object>> salaries = managementService.executeCustomSql(customSqlExecution);
        assertEquals(5, salaries.size());
        for (int i = 0; i < salaries.size(); i++) {
            Map<String, Object> salary = salaries.get(i);


Thank you very much!