FetchAndLock using asyncResponseTimeout returns empty body

Using postman I can call the REST API for fetchAndLock. If I don’t use asyncResponseTimeout, I get an empty array in the body. If I use asyncResponseTimeout, then the body returned is empty, after the timeout.
This causes the External Task client library to throw an exception:

2018-11-02 16:21:06.205 DEBUG 4972 --- [criptionManager] org.apache.http.wire                     : http-outgoing-0 >> "POST /workflow/rest/external-task/fetchAndLock HTTP/1.1[\r][\n]"

2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “User-Agent: Camunda External Task Client[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “Content-Type: application/json[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “Content-Length: 253[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “Host: localhost:8080[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “Connection: Keep-Alive[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “Accept-Encoding: gzip,deflate[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “Authorization: Bearer xxx[\r][\n]”
2018-11-02 16:21:06.205 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “[\r][\n]”
2018-11-02 16:21:06.206 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 >> “{“workerId”:“b-627faed0-1a4d-4a9f-9ecd-6ef6fc39b2c9”,“maxTasks”:1,“asyncResponseTimeout”:30000,“topics”:[{“topicName”:“myTopic”,“lockDuration”:5000,“variables”:[“x”,“y”,“z”],“businessKey”:null}]}”
2018-11-02 16:21:36.237 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “HTTP/1.1 200 [\r][\n]”
2018-11-02 16:21:36.238 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “conversationId: 50587581-550f-4fc9-92c1-853c4258d7f0[\r][\n]”
2018-11-02 16:21:36.238 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “Set-Cookie: JSESSIONID=3EDFA399EB9034E6CF7DD485A5D11395; Path=/bpg-csp-workflow; HttpOnly[\r][\n]”
2018-11-02 16:21:36.238 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “Content-Type: application/json[\r][\n]”
2018-11-02 16:21:36.238 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “Content-Length: 0[\r][\n]”
2018-11-02 16:21:36.239 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “Date: Fri, 02 Nov 2018 16:21:36 GMT[\r][\n]”
2018-11-02 16:21:36.239 DEBUG 4972 — [criptionManager] org.apache.http.wire : http-outgoing-0 << “[\r][\n]”
2018-11-02 16:21:36.287 ERROR 4972 — [criptionManager] org.camunda.bpm.client : TASK/CLIENT-03001 Exception while fetch and lock task.

org.camunda.bpm.client.impl.EngineClientException: TASK/CLIENT-02005 Exception while mapping json object to response dto class ‘class [Lorg.camunda.bpm.client.task.impl.ExternalTaskImpl;’
at org.camunda.bpm.client.impl.EngineClientLogger.exceptionWhileMappingJsonObject(EngineClientLogger.java:47) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.impl.RequestExecutor.deserializeResponse(RequestExecutor.java:140) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.impl.RequestExecutor$1.handleEntity(RequestExecutor.java:115) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
at org.apache.http.impl.client.AbstractResponseHandler.handleResponse(AbstractResponseHandler.java:73) ~[httpclient-4.5.5.jar:4.5.5]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:223) ~[httpclient-4.5.5.jar:4.5.5]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:165) ~[httpclient-4.5.5.jar:4.5.5]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:140) ~[httpclient-4.5.5.jar:4.5.5]
at org.camunda.bpm.client.impl.RequestExecutor.executeRequest(RequestExecutor.java:82) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.impl.RequestExecutor.postRequest(RequestExecutor.java:68) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.impl.EngineClient.fetchAndLock(EngineClient.java:68) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.topic.impl.TopicSubscriptionManager.fetchAndLock(TopicSubscriptionManager.java:126) [camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.topic.impl.TopicSubscriptionManager.acquire(TopicSubscriptionManager.java:95) [camunda-external-task-client-1.0.0.jar:1.0.0]
at org.camunda.bpm.client.topic.impl.TopicSubscriptionManager.run(TopicSubscriptionManager.java:81) [camunda-external-task-client-1.0.0.jar:1.0.0]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
at [Source: (org.apache.http.impl.io.EmptyInputStream); line: 1, column: 0]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4145) ~[jackson-databind-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4000) ~[jackson-databind-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3070) ~[jackson-databind-2.9.6.jar:2.9.6]
at org.camunda.bpm.client.impl.RequestExecutor.deserializeResponse(RequestExecutor.java:136) ~[camunda-external-task-client-1.0.0.jar:1.0.0]
… 12 common frames omitted
Using curl, I can recreate the issue.

curl --include http://localhost:8080/workflow/rest/engine/default/external-task/fetchAndLock -H ‘Accept: application/json’ -H ‘Authorization: Bearer xxx’ -H ‘Content-Type: application/json’ -H ‘cache-control: no-cache’ -d ‘{
“workerId”:“Nick”,
“maxTasks”:1,
“usePriority”:true,
“asyncResponseTimeout”: 10000,
“topics”:
[{“topicName”: “myTopic”,
“lockDuration”: 10000,
“variables”: [“x”]
}]
}’
HTTP/1.1 200
conversationId: 1ded4c04-d147-442d-a8b7-b92699921596
Set-Cookie: JSESSIONID=C634E0A76D81FE9A729CA76EE4EBA34A; Path=/workflow; HttpOnly
Content-Type: application/json
Content-Length: 0
Date: Fri, 02 Nov 2018 16:38:42 GMT

curl --include http://localhost:8080/workflow/rest/engine/default/external-task/fetchAndLock -H ‘Accept: application/json’ -H ‘Authorization: Bearer xxx’ -H ‘Content-Type: application/json’ -H ‘cache-control: no-cache’ -d ‘{
“workerId”:“Nick”,
“maxTasks”:1,
“usePriority”:true,
“topics”:
[{“topicName”: “myTopic”,
“lockDuration”: 10000,
“variables”: [“x”]
}]
}’
HTTP/1.1 200
conversationId: fb11c393-fe1a-46a8-9415-58e182a73550
Set-Cookie: JSESSIONID=3AD57C22ADDF400BB196828059BD1726; Path=/workflow; HttpOnly
Content-Type: application/json
Content-Length: 2
Date: Fri, 02 Nov 2018 16:39:01 GMT

[]

I guess nobody thinks this is a defect?

Hi Nick,

I tried to reproduce the problem but I didn’t succeed.
If there are external tasks available, are you able to get the expected response body?

Cheers,
Tassilo

1 Like

This problem occurs only if there are no external tasks available. The body returned from the REST call is different if the asyncResponseTimeout is used. This is a problem for the External Task Client library, as it always throws an exception when the body is empty (rather than the correct JSON for an empty list).

Our experience is that this has two effects:

  1. Nasty exceptions being logged by the external task client library.
  2. We seem to lose the ability to receive an external task via the external task client, when one is pending, but only after an undetermined length of time.

Now to answer your question, I believe that the server does have the correct body when there are external tasks available.

Even though the problem manifests via the External Task client library, I think the correct fix is to make the REST service return a consistent JSON for the empty list in the body.

BTW, I am using 7.9 and the spring boot starters for rest and webapp (and also the dependency order workaround) so that our server has the correct REST engine library.

Thanks,

Nick

An update on this problem. When I tested the 7.10.0 docker image, it worked as expected. I passed the asyncResponseTimeout in the body of the fetchAndLock call, and after the appropriate time, I got an empty list back in the body
Unfortunately we don’t use the docker image, but we build ourselves a spring boot application, so I upgraded our build to the following:
springBootVersion = ‘2.1.1.RELEASE’
camundaSpringBootStarterVersion = ‘3.2.1’
camundaVersion = ‘7.10.0’
camundaSpinVersion = ‘1.6.5’
camelVersion = ‘2.23.1’
groovyVersion = ‘2.5.5’
spockVersion = ‘1.2-groovy-2.5’
and
implementation(“org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter-rest:${camundaSpringBootStarterVersion}”){
_ exclude group: ‘org.camunda.bpm.springboot’, module: ‘camunda-bpm-spring-boot-starter-test’_
}
implementation “org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter-webapp:${camundaSpringBootStarterVersion}”

In my built version, the defect remains. When I call fetchAndLock with asyncResponseTimeout provided, in my spring boot application I get an empty body back!

I will try attaching to the docker image and seeing if it has different jars than the app I’m building.

Nick.

The md5 checksums in the docker image don’t match the md5 of the camunda-engine-rest-jaxrs2-7.10.0.jar.
In the central Maven repository the md5 (http://central.maven.org/maven2/org/camunda/bpm/camunda-engine-rest-jaxrs2/7.10.0/camunda-engine-rest-jaxrs2-7.10.0.jar.md5) is:
$ md5sum camunda-engine-rest-jaxrs2-7.10.0.jar
f01112ca1e9a34471b24eafeca0eb16a *camunda-engine-rest-jaxrs2-7.10.0.jar

In the docker image its:
bash-4.4$ md5sum camunda-engine-rest-jaxrs2-7.10.0.jar
8c08bce1ef513aa0ec23e00b3d9b1f00 camunda-engine-rest-jaxrs2-7.10.0.jar

Any idea where the docker image gets its copy of the jar from?

Nick.

Hi @NickTheArchitect,

about which docker image are you talking? Could you post a link?

Cheers,
Tassilo

https://hub.docker.com/r/camunda/camunda-bpm-platform
The github repo is at https://github.com/camunda/docker-camunda-bpm-platform

HTH, Nick

The one that works, from the docker image, is from the file https://app.camunda.com/nexus/content/repositories/camunda-bpm/org/camunda/bpm/tomcat/camunda-bpm-tomcat/7.10.0/camunda-bpm-tomcat-7.10.0.tar.gz
When extracted the md5sum is:
8c08bce1ef513aa0ec23e00b3d9b1f00 *./tmp/server/apache-tomcat-9.0.12/webapps/engine-rest/WEB-INF/lib/camunda-engine-rest-jaxrs2-7.10.0.jar
This is clearly a better version of the jar that that available from Maven central (http://central.maven.org/maven2/org/camunda/bpm/camunda-engine-rest-jaxrs2/7.10.0/camunda-engine-rest-jaxrs2-7.10.0.jar), which has a md5 checksum of:
f01112ca1e9a34471b24eafeca0eb16a
@tasso94 - Is it possible to get the better camunda-engine-rest-jaxrs2 deployed into Maven central? If only as 7.10.1, or something?

Thanks, Nick

Hi @NickTheArchitect,

I will look into the artefacts and come back to you tomorrow at the latest.

Cheers,
Tassilo

Hi @NickTheArchitect,

I still cannot reproduce your problem.

This are the steps I have performed:

  1. I use spring-boot-starter-rest:3.2.1
  2. No External Tasks are available to ‘Fetch and Lock’
  3. I perform a POST request against http://localhost:8080/rest/external-task/fetchAndLock with the following payload:
    {"maxTasks": 1, "workerId": "aWorkerId", "asyncResponseTimeout": 20000, "topics": [{"topicName": "aTopicName", "lockDuration": 3000}]}
    

Observed behavior
After the asyncResponseTimeout is due, I get the following response: []

Could you please provide an example project with a unit test case that reproduces your problem?

Cheers,
Tassilo

Hi. Any update on this? I have the same error. I use camunda 7.11 emedded in Spring Boot app and I hit into the same behavior as Nick.
I even tried to bump up version of camunda spring boot starter to 7.14.0. It didn’t help. I must be caused by some specific dependency in my stack.
Find my build.gradle below.

import com.commercehub.gradle.plugin.avro.GenerateAvroJavaTask

buildscript {
    ext {
        gitProperties = '1.4.17'
        hazelcastVersion = '3.12.6'
        hcSpringWSVersion = '1.5.0'
        h2Version = '1.4.191'
        kotlinVersion = '1.3.72'
        springBootVersion = '2.3.3.RELEASE'
        springJdbc = '4.3.11.RELEASE'
        springVersion = '5.2.7.RELEASE'
        springWsVersion = '2.4.0.RELEASE'
        springfox = '2.6.0'
        mybatisVersion = '3.4.4'
        mybatisSpringVersion = '1.3.0'
        oracleDriverVersion = '12.1.0.2'
        wsCommonsVersion = '3.0.10'
        testingJUnitVersion = '4.12'
        testingMockitoKotlinVersion = '1.6.0'
        javaUuidGenerator = '3.1.2'
        apacheCommonsMathVersion = '3.0'
        apacheCommonsLang = '3.4'
        digitalSignatureVersion = '1.4.0'
        kafka = '2.4.5.RELEASE'
        avroPluginVersion = '0.17.0'
        avroVersion = '1.9.0'
        micrometerVersion = '1.0.6'
        camundaSpringBootStarterVersion = '3.3.10'
        camundaSpringBootStarterTestVersion = '2.2.0'
        rabbitMockVersion = '1.0.10'
        vectorUtilsVersion = '0.2.6'
    }

    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath "com.commercehub.gradle.plugin:gradle-avro-plugin:0.9.1"
        classpath "org.liquibase:liquibase-gradle-plugin:2.0.1"
    }

    repositories {
        mavenLocal()
        maven { url "https://nexuscn.cz.infra/repository/mirror/" }
    }
}

plugins {
    id "org.jetbrains.kotlin.plugin.allopen" version "1.2.31"
    id "org.jetbrains.kotlin.jvm" version "1.3.72"
    id "org.sonarqube" version "2.8"
}

apply plugin: 'java'
//apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'idea'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'org.springframework.boot'
apply plugin: 'com.commercehub.gradle.plugin.avro-base'
apply plugin: 'liquibase'
apply plugin: 'jacoco'

compileKotlin {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "11"
        allWarningsAsErrors = false
    }
}

compileTestKotlin {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "11"
    }
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
    kotlinOptions {
        jvmTarget = "11"
    }
}

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

dependencyManagement {
    imports {
        mavenBom "org.springframework.boot:spring-boot-starter-parent:$springBootVersion"
        mavenBom "org.camunda.bpm:camunda-bom:7.11.0"
    }
}

configurations {
    mybatis
    database
    compile.extendsFrom mybatis
    integrationTestCompile.extendsFrom testCompile, implementation
    integrationTestRuntime.extendsFrom testRuntime
    featureTestCompile.extendsFrom testCompile, implementation
    featureTestRuntime.extendsFrom testRuntime
    compile.exclude module: 'tomcat-embed-websocket'
}

bootJar {
    mainClassName = 'cz.embedit.cn.scoring.BartScoringServiceApplicationKt'
    layered {
        includeLayerTools = true
    }
}

springBoot {
    buildInfo {
        properties {
            version = project.version
        }
    }
}

group 'net.homecredit.cn.bart'

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}"
    compile "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"

    compile "com.fasterxml.jackson.core:jackson-core"
    compile "com.fasterxml.jackson.core:jackson-databind"
    compile "com.fasterxml.jackson.module:jackson-module-kotlin"
    compile "com.fasterxml.jackson.core:jackson-annotations"
    compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"

    compile "org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter:${camundaSpringBootStarterVersion}"
    compile "org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter-rest:${camundaSpringBootStarterVersion}"
    compile "org.camunda.bpm:camunda-engine-plugin-spin"
    compile "org.camunda.spin:camunda-spin-core"
    compile "org.camunda.spin:camunda-spin-dataformat-json-jackson"

    compile "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    compile("org.springframework.boot:spring-boot-starter-validation")
    compile("org.springframework.boot:spring-boot-starter-validation:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-data-cassandra:${springBootVersion}")
    compile "de.codecentric:spring-boot-admin-starter-client:2.1.6"
    compile "com.oracle:ojdbc7:${oracleDriverVersion}"
    compile('org.springframework.boot:spring-boot-starter-security')
    compile "org.springframework.boot:spring-boot-starter-data-redis"
    compile "org.springframework:spring-web"
    compile "org.springframework.kafka:spring-kafka"
    compile "org.springframework.boot:spring-boot-starter-amqp"
    compile("org.springframework:spring-aop")
    compile("org.springframework:spring-jdbc")

    compile "com.hazelcast:hazelcast:${hazelcastVersion}"
    compile "com.hazelcast:hazelcast-kubernetes:1.5.3"

    compile "com.oracle:ojdbc7:${oracleDriverVersion}"
    compile('javax.servlet:javax.servlet-api')
    compile "org.apache.commons:commons-math3:${apacheCommonsMathVersion}"
    compile "org.apache.commons:commons-lang3:${apacheCommonsLang}"
    compile "org.aspectj:aspectjweaver:1.8.14"

    compile "io.micrometer:micrometer-registry-prometheus"

    compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
    compile("io.springfox:springfox-swagger2:${springfox}")
    compile("io.springfox:springfox-swagger-ui:${springfox}")
    compile("com.fasterxml.uuid:java-uuid-generator:${javaUuidGenerator}")
    compile 'org.postgresql:postgresql:9.4.1212'

    compile "ch.qos.logback:logback-classic:1.2.3"
    compile "ch.qos.logback.contrib:logback-json-classic:0.1.5"
    compile "ch.qos.logback.contrib:logback-jackson:0.1.5"
    compile "net.logstash.logback:logstash-logback-encoder:6.4"

    compile "org.springframework.ws:spring-ws-core"

    compile "net.homecredit.cn.infrastructure:digital-signature:${digitalSignatureVersion}"
    compile "net.homecredit.commons:hc-spring-ws:${hcSpringWSVersion}"
    compile("net.homecredit.ws:ws-commons-all:${wsCommonsVersion}") {
        exclude group: 'log4j'
        exclude group: 'org.springframework'
        exclude group: 'xerces'
    }
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
    compile group: 'redis.clients', name: 'jedis', version: '3.1.0'

    compile("org.apache.avro:avro:${avroVersion}")

    compile "org.springframework.boot:spring-boot-starter-amqp"
    compile('io.confluent:kafka-avro-serializer:3.2.1') {
        exclude group: 'org.slf4j'
    }
    compile "net.homecredit:vector-utils:${vectorUtilsVersion}"

    implementation "net.homecredit:data-mapper:0.4.6"

    mybatis "org.mybatis:mybatis:${mybatisVersion}", "org.mybatis.spring.boot:mybatis-spring-boot-starter:${mybatisSpringVersion}"

    testCompile "org.springframework.boot:spring-boot-starter-test:${springBootVersion}"
    testCompile "junit:junit:${testingJUnitVersion}"
    testCompile "com.nhaarman:mockito-kotlin:${testingMockitoKotlinVersion}"


    testCompile "com.h2database:h2:${h2Version}"
    testCompile "com.oracle:ojdbc7:${oracleDriverVersion}"
    testCompile "org.camunda.bpm.extension.springboot:camunda-bpm-spring-boot-starter-test:${camundaSpringBootStarterTestVersion}"

    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile group: 'org.springframework.security', name: 'spring-security-test', version: '4.0.0.RELEASE'
    testCompile("org.springframework.boot:spring-boot-starter-data-cassandra")
    featureTestCompile "com.github.fridujo:rabbitmq-mock:${rabbitMockVersion}"

    featureTestCompile 'io.cucumber:cucumber-java:4.2.2'
    featureTestCompile 'io.cucumber:cucumber-junit:4.2.2'
    featureTestCompile 'io.cucumber:cucumber-spring:4.2.2'

    integrationTestCompile 'io.cucumber:cucumber-java:4.2.2'
    integrationTestCompile 'io.cucumber:cucumber-junit:4.2.2'

    liquibaseRuntime group: 'net.homecredit', name: 'liquibase-ext', version: '3.5.1-23'
    liquibaseRuntime group: 'com.oracle', name: 'ojdbc7', version: '12.1.0.2'
    liquibaseRuntime 'org.liquibase:liquibase-core:3.6.3'
    liquibaseRuntime 'org.postgresql:postgresql:9.4.1212'
    liquibaseRuntime 'com.oracle:ojdbc7:12.1.0.2'
    liquibaseRuntime 'ch.qos.logback:logback-core:1.2.3'
    liquibaseRuntime 'ch.qos.logback:logback-classic:1.2.3'

    testCompile 'org.camunda.bpm.extension:camunda-bpm-assert-scenario:0.2'
    testCompile group: 'org.camunda.bpm.assert', name: 'camunda-bpm-assert', version: '4.0.0'
    testCompile 'org.liquibase:liquibase-core:3.6.3'
}

repositories {
    mavenLocal()
    maven { url "https://nexuscn.cz.infra/repository/mirror/" }
}

task generateAvro(type: GenerateAvroJavaTask) {
    source("src/main/resources/avro")
    outputDir = file("$buildDir/generated-src/main/java/avro")
    fieldVisibility = "PRIVATE"
}

sourceSets {
    main {
        java {
            srcDir "$buildDir/generated-src/main/java/avro"
        }
    }
    database {
        resources {
            srcDir "$buildDir/src/database/resources"
        }
    }
    integrationTest {
        kotlin {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/test-integration/kotlin')
        }
        resources {
            srcDir file('src/test-integration/resources')
        }
    }
    featureTest {
        kotlin {
            compileClasspath += main.output
            runtimeClasspath += main.output + database.output
            srcDir file('src/test-feature/kotlin')
        }
        resources {
            srcDir file('src/test-feature/resources')
        }
    }
}

idea {
    module {
        generatedSourceDirs += file("$buildDir/generated-src/main/java/avro")

        testSourceDirs += project.sourceSets.integrationTest.kotlin.srcDirs
        testSourceDirs += project.sourceSets.integrationTest.resources.srcDirs

        testSourceDirs += project.sourceSets.featureTest.kotlin.srcDirs
        testSourceDirs += project.sourceSets.featureTest.resources.srcDirs
    }
}

jacocoTestReport {
    jacoco {
        toolVersion = "0.8.5"
    }

    reports {
        xml.enabled true
        csv.enabled true
        html.enabled true
    }

    afterEvaluate {
        getClassDirectories().setFrom(classDirectories.files.collect {
            fileTree(dir: it, exclude: [
                    '**/avro/**',
                    'cz/embedit/cn/scoring/amqp/amqp/domain/**',
                    'cz/embedit/cn/scoring/type/**',
                    'cz/embedit/cn/scoring/config/**',
                    '**/*Config*',
                    '**/*Configuration*',
                    '**/model/**',
                    '**/dto/**',
                    'cz/embedit/cn/scoring/dataflow/kafka/events/**'
            ])
        })
    }
}

task integrationTest(type: Test) {
    testClassesDirs = sourceSets.integrationTest.output.classesDirs
    classpath = sourceSets.integrationTest.runtimeClasspath
    outputs.upToDateWhen { false }
}

task featureTest(type: Test) {
    testClassesDirs = sourceSets.featureTest.output.classesDirs
    classpath = sourceSets.featureTest.runtimeClasspath
    outputs.upToDateWhen { false }
}

def workflowChangeLog = "$projectDir/src/database/resources/workflow/workflow.changelog-master.xml"
task('liquibaseWorkflow').doLast {
    liquibase {
        activities {
            main {
                changeLogFile workflowChangeLog
                url url
                username username
                password password
                contexts System.getProperty('database.profile') ?: 'oracle'
                liquibaseSchemaName System.getProperty('database.defaultSchemaName')
                defaultSchemaName System.getProperty('database.defaultSchemaName')
            }
        }
    }
}

def scoringChangeLog = "$projectDir/src/database/resources/scoring/scoring.changelog-master.xml"
task('liquibaseScoring').doLast {
    liquibase {
        activities {
            main {
                changeLogFile scoringChangeLog
                url url
                username username
                password password
                contexts System.getProperty('database.profile') ?: 'oracle'
                liquibaseSchemaName System.getProperty('database.defaultSchemaName')
                defaultSchemaName System.getProperty('database.defaultSchemaName')
            }
        }
    }
}

task liquibaseJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'liquibase.integration.commandline.Main'
    }
    from(sourceSets.database.resources) {
        into 'db'
    }
    from configurations.liquibaseRuntime.collect { it.isDirectory() ? it : zipTree(it) }
    baseName = 'bart-scoring-service-db'
}

task avroZip(type: Zip) {
    archiveName 'bart-scoring-service-avro-' + version + '.zip'
    destinationDir file("$buildDir/libs/")
    from("src/main/resources/avro/kafka") {
        include '*.avsc'
    }
    description "Assemble archive $archiveName into ${relativePath(destinationDir)}"
}

compileJava.source(generateAvro.outputs)
compileKotlin.dependsOn generateAvro
check.dependsOn integrationTest, featureTest

@tasso94 @NickTheArchitect : could you please share the example project, How you are accessing the Locked external tasks from the fetchAndLock method by calling from the external task client.

If your “http://localhost:8080/rest/external-task/fetchAndLock” is secured with JWT how to access it from external task client.
Suppose instead of localhost if my base url is something like below

camunda.bpm.client.base-url=https://camunda-engine-service/process/engine-rest

how to call from external task client?

Just because we encountered the same issue and this post supported that it might be a bug. For us it was a problem in our own spring boot application that contained a web filter that set the response wrong when using long polling (asyncResponseTimeout).