diff --git a/.ci/jenkins/Jenkinsfile.deploy b/.ci/jenkins/Jenkinsfile.deploy
index 58e0c532bb..51afe0271e 100644
--- a/.ci/jenkins/Jenkinsfile.deploy
+++ b/.ci/jenkins/Jenkinsfile.deploy
@@ -119,7 +119,9 @@ pipeline {
if (isRelease()) {
releaseUtils.gpgImportKeyFromStringWithoutPassword(getReleaseGpgSignKeyCredsId())
- mavenCommand.withProfiles(['apache-release'])
+ mavenCommand
+ .withProfiles(['apache-release'])
+ .withProperty('only.reproducible')
}
configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
diff --git a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-embedded/pom.xml b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-embedded/pom.xml
index 72383b29ad..d244649644 100644
--- a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-embedded/pom.xml
+++ b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-embedded/pom.xml
@@ -100,18 +100,39 @@
+
+ maven-resources-plugin
+
+
+ generate-resources
+
+ copy-resources
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+ ${common.test.resources.dir}
+
+ **/*.bpmn
+ **/*.sw.json
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+
+
-
-
- src/main/resources
-
-
- ${common.test.resources.dir}
-
- **/*.bpmn
- **/*.sw.json
-
-
-
diff --git a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-knative-eventing/pom.xml b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-knative-eventing/pom.xml
index 309ff02dcb..e105b0f06a 100644
--- a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-knative-eventing/pom.xml
+++ b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-knative-eventing/pom.xml
@@ -88,18 +88,39 @@
+
+ maven-resources-plugin
+
+
+ generate-resources
+
+ copy-resources
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+ ${common.test.resources.dir}
+
+ **/*.bpmn
+ **/*.sw.json
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+
+
-
-
- src/main/resources
-
-
- ${common.test.resources.dir}
-
- **/*.bpmn
- **/*.sw.json
-
-
-
diff --git a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-management/pom.xml b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-management/pom.xml
index ade7cbe17e..6cccd4aa7a 100644
--- a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-management/pom.xml
+++ b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-management/pom.xml
@@ -79,7 +79,6 @@
io.quarkus
quarkus-maven-plugin
- ${version.io.quarkus}
true
@@ -91,18 +90,39 @@
+
+ maven-resources-plugin
+
+
+ generate-resources
+
+ copy-resources
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+ ${common.test.resources.dir}
+
+ **/*.bpmn
+ **/*.sw.json
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+
+
-
-
- src/main/resources
-
-
- ${common.test.resources.dir}
-
- **/*.bpmn
- **/*.sw.json
-
-
-
diff --git a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-messaging/pom.xml b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-messaging/pom.xml
index 3ccd6395dd..fba2a2c5f1 100644
--- a/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-messaging/pom.xml
+++ b/apps-integration-tests/integration-tests-jobs-service/integration-tests-jobs-service-quarkus/integration-tests-jobs-service-quarkus-messaging/pom.xml
@@ -94,24 +94,10 @@
-
-
- src/main/resources
-
-
- ${common.test.resources.dir}
-
- **/*.bpmn
- **/*.sw.json
-
-
-
-
io.quarkus
quarkus-maven-plugin
- ${version.io.quarkus}
true
@@ -123,6 +109,39 @@
+
+ maven-resources-plugin
+
+
+ generate-resources
+
+ copy-resources
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+ ${common.test.resources.dir}
+
+ **/*.bpmn
+ **/*.sw.json
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/src/main/resources/shared
+
+
+
+
diff --git a/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/pom.xml b/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/pom.xml
index 1ad411f350..9aafdb5dad 100644
--- a/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/pom.xml
+++ b/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/pom.xml
@@ -87,10 +87,6 @@
kogito-test-utils
compile
-
- org.keycloak
- keycloak-core
-
diff --git a/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/src/main/java/org/kie/kogito/it/trusty/AbstractTrustyExplainabilityEnd2EndIT.java b/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/src/main/java/org/kie/kogito/it/trusty/AbstractTrustyExplainabilityEnd2EndIT.java
index 4207ff9ae6..0ce911613a 100644
--- a/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/src/main/java/org/kie/kogito/it/trusty/AbstractTrustyExplainabilityEnd2EndIT.java
+++ b/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-common/src/main/java/org/kie/kogito/it/trusty/AbstractTrustyExplainabilityEnd2EndIT.java
@@ -29,7 +29,6 @@
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
-import org.keycloak.representations.AccessTokenResponse;
import org.kie.kogito.explainability.api.CounterfactualSearchDomain;
import org.kie.kogito.explainability.api.CounterfactualSearchDomainCollectionValue;
import org.kie.kogito.explainability.api.CounterfactualSearchDomainStructureValue;
@@ -183,7 +182,7 @@ public void doTest() {
.param(KEYCLOAK_CLIENT_SECRET_PARAM_NAME, KEYCLOAK_CLIENT_SECRET_PARAM_VALUE)
.when()
.post(KEYCLOAK_ACCESS_TOKEN_PATH)
- .as(AccessTokenResponse.class).getToken();
+ .jsonPath().get("access_token");
assertNotNull(accessToken);
diff --git a/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-springboot/pom.xml b/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-springboot/pom.xml
index 2340d6020b..5219530993 100644
--- a/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-springboot/pom.xml
+++ b/apps-integration-tests/integration-tests-trusty-service/integration-tests-trusty-service-springboot/pom.xml
@@ -33,7 +33,7 @@
org.kie.kogito/integration-tests-trusty-service-springboot:${project.version}
**/KogitoApplication.java
- 3.3.1
+ 3.4.4
eclipse-temurin:17-jre
diff --git a/data-index/data-index-graphql/src/main/resources/basic.schema.graphqls b/data-index/data-index-graphql/src/main/resources/basic.schema.graphqls
index 741c0d4e89..0317ec61c5 100644
--- a/data-index/data-index-graphql/src/main/resources/basic.schema.graphqls
+++ b/data-index/data-index-graphql/src/main/resources/basic.schema.graphqls
@@ -96,6 +96,7 @@ type ProcessInstance {
identity: String
createdBy: String
updatedBy: String
+ slaDueDate: DateTime
}
type ProcessInstanceError {
@@ -135,6 +136,7 @@ type NodeInstance {
exit: DateTime
definitionId: String!
nodeId: String!
+ slaDueDate: DateTime
}
enum MilestoneStatus {
diff --git a/data-index/data-index-service/data-index-service-common/pom.xml b/data-index/data-index-service/data-index-service-common/pom.xml
index a3eb73abd7..4abb945f17 100644
--- a/data-index/data-index-service/data-index-service-common/pom.xml
+++ b/data-index/data-index-service/data-index-service-common/pom.xml
@@ -141,11 +141,6 @@
json-unit-assertj
test
-
- org.keycloak
- keycloak-core
- test
-
org.kie.kogito
kogito-quarkus-test-utils
diff --git a/data-index/data-index-service/data-index-service-common/src/test/java/org/kie/kogito/index/service/AbstractKeycloakIntegrationIndexingServiceIT.java b/data-index/data-index-service/data-index-service-common/src/test/java/org/kie/kogito/index/service/AbstractKeycloakIntegrationIndexingServiceIT.java
index f2fcd37cd0..c91e5195a5 100644
--- a/data-index/data-index-service/data-index-service-common/src/test/java/org/kie/kogito/index/service/AbstractKeycloakIntegrationIndexingServiceIT.java
+++ b/data-index/data-index-service/data-index-service-common/src/test/java/org/kie/kogito/index/service/AbstractKeycloakIntegrationIndexingServiceIT.java
@@ -20,7 +20,6 @@
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Test;
-import org.keycloak.representations.AccessTokenResponse;
import org.kie.kogito.testcontainers.KogitoKeycloakContainer;
import org.kie.kogito.testcontainers.quarkus.KeycloakQuarkusTestResource;
@@ -97,6 +96,6 @@ private String getAccessToken(String userName) {
.param("client_secret", KogitoKeycloakContainer.CLIENT_SECRET)
.when()
.post(keycloakURL + "/protocol/openid-connect/token")
- .as(AccessTokenResponse.class).getToken();
+ .jsonPath().get("access_token");
}
}
diff --git a/data-index/data-index-service/data-index-service-infinispan/pom.xml b/data-index/data-index-service/data-index-service-infinispan/pom.xml
index d9134e9cef..375cdf8cc1 100644
--- a/data-index/data-index-service/data-index-service-infinispan/pom.xml
+++ b/data-index/data-index-service/data-index-service-infinispan/pom.xml
@@ -101,11 +101,6 @@
kogito-quarkus-test-utils
test
-
- org.keycloak
- keycloak-core
- test
-
org.awaitility
awaitility
diff --git a/data-index/data-index-service/data-index-service-inmemory/pom.xml b/data-index/data-index-service/data-index-service-inmemory/pom.xml
index 9b1586fbcd..4dd51a953a 100644
--- a/data-index/data-index-service/data-index-service-inmemory/pom.xml
+++ b/data-index/data-index-service/data-index-service-inmemory/pom.xml
@@ -89,11 +89,6 @@
kogito-quarkus-test-utils
test
-
- org.keycloak
- keycloak-core
- test
-
org.awaitility
awaitility
diff --git a/data-index/data-index-service/data-index-service-mongodb/pom.xml b/data-index/data-index-service/data-index-service-mongodb/pom.xml
index 118314743f..7c2ead3652 100644
--- a/data-index/data-index-service/data-index-service-mongodb/pom.xml
+++ b/data-index/data-index-service/data-index-service-mongodb/pom.xml
@@ -95,11 +95,6 @@
kogito-quarkus-test-utils
test
-
- org.keycloak
- keycloak-core
- test
-
org.awaitility
awaitility
diff --git a/data-index/data-index-service/data-index-service-postgresql/pom.xml b/data-index/data-index-service/data-index-service-postgresql/pom.xml
index 4db0252d0c..43f999c6fa 100644
--- a/data-index/data-index-service/data-index-service-postgresql/pom.xml
+++ b/data-index/data-index-service/data-index-service-postgresql/pom.xml
@@ -94,11 +94,6 @@
kogito-quarkus-test-utils
test
-
- org.keycloak
- keycloak-core
- test
-
org.awaitility
awaitility
diff --git a/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/NodeInstance.java b/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/NodeInstance.java
index 1e22527c59..ab9df6cadd 100644
--- a/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/NodeInstance.java
+++ b/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/NodeInstance.java
@@ -38,6 +38,8 @@ public class NodeInstance {
@JsonProperty("leaveTime")
private ZonedDateTime exit;
+ private ZonedDateTime slaDueDate;
+
@JsonProperty("nodeDefinitionId")
private String definitionId;
@@ -97,6 +99,14 @@ public void setName(String name) {
this.name = name;
}
+ public ZonedDateTime getSlaDueDate() {
+ return slaDueDate;
+ }
+
+ public void setSlaDueDate(ZonedDateTime slaDueDate) {
+ this.slaDueDate = slaDueDate;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -125,6 +135,7 @@ public String toString() {
", type='" + type + '\'' +
", enter=" + enter +
", exit=" + exit +
+ ", slaDueDate=" + slaDueDate +
", definitionId='" + definitionId + '\'' +
'}';
}
diff --git a/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/ProcessInstanceMeta.java b/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/ProcessInstanceMeta.java
index d211ea198d..09441ca019 100644
--- a/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/ProcessInstanceMeta.java
+++ b/data-index/data-index-storage/data-index-storage-api/src/main/java/org/kie/kogito/index/model/ProcessInstanceMeta.java
@@ -49,6 +49,7 @@ public class ProcessInstanceMeta {
@JsonProperty("updatedBy")
private String updatedBy;
private ZonedDateTime lastUpdate;
+ private ZonedDateTime slaDueDate;
public String getId() {
return id;
@@ -186,6 +187,14 @@ public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
+ public ZonedDateTime getSlaDueDate() {
+ return slaDueDate;
+ }
+
+ public void setSlaDueDate(ZonedDateTime slaDueDate) {
+ this.slaDueDate = slaDueDate;
+ }
+
@Override
public String toString() {
return "ProcessInstanceMeta{" +
diff --git a/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceNodeDataEventMerger.java b/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceNodeDataEventMerger.java
index d800dfd226..bb7c39a5bc 100644
--- a/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceNodeDataEventMerger.java
+++ b/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceNodeDataEventMerger.java
@@ -63,6 +63,7 @@ public ProcessInstance merge(ProcessInstance pi, ProcessInstanceDataEvent> dat
nodeInstance.setNodeId(body.getNodeDefinitionId());
nodeInstance.setName(body.getNodeName());
nodeInstance.setType(body.getNodeType());
+ nodeInstance.setSlaDueDate(toZonedDateTime(body.getSlaDueDate()));
ZonedDateTime eventDate = toZonedDateTime(body.getEventDate());
switch (body.getEventType()) {
case EVENT_TYPE_ENTER:
diff --git a/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceStateDataEventMerger.java b/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceStateDataEventMerger.java
index b49036fb0c..a7be6d0ea3 100644
--- a/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceStateDataEventMerger.java
+++ b/data-index/data-index-storage/data-index-storage-common/src/main/java/org/kie/kogito/index/storage/merger/ProcessInstanceStateDataEventMerger.java
@@ -63,6 +63,7 @@ public ProcessInstance merge(ProcessInstance pi, ProcessInstanceDataEvent> dat
pi.setLastUpdate(toZonedDateTime(event.getTime()));
pi.setDefinition(definitions(event));
pi.setUpdatedBy(event.getData().getEventUser());
+ pi.setSlaDueDate(toZonedDateTime(event.getData().getSlaDueDate()));
LOGGER.debug("Value after merging: {}", pi);
return pi;
}
diff --git a/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/NodeInstanceMarshaller.java b/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/NodeInstanceMarshaller.java
index 194ad08caa..dd4b5f557c 100644
--- a/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/NodeInstanceMarshaller.java
+++ b/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/NodeInstanceMarshaller.java
@@ -42,6 +42,7 @@ public NodeInstance readFrom(ProtoStreamReader reader) throws IOException {
node.setExit(dateToZonedDateTime(reader.readDate("exit")));
node.setDefinitionId(reader.readString("definitionId"));
node.setNodeId(reader.readString("nodeId"));
+ node.setSlaDueDate(dateToZonedDateTime(reader.readDate("slaDueDate")));
return node;
}
@@ -54,6 +55,7 @@ public void writeTo(ProtoStreamWriter writer, NodeInstance node) throws IOExcept
writer.writeDate("exit", zonedDateTimeToDate(node.getExit()));
writer.writeString("definitionId", node.getDefinitionId());
writer.writeString("nodeId", node.getNodeId());
+ writer.writeDate("slaDueDate", zonedDateTimeToDate(node.getSlaDueDate()));
}
@Override
diff --git a/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/ProcessInstanceMarshaller.java b/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/ProcessInstanceMarshaller.java
index ab391703aa..3e46ea2bf3 100644
--- a/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/ProcessInstanceMarshaller.java
+++ b/data-index/data-index-storage/data-index-storage-infinispan/src/main/java/org/kie/kogito/index/infinispan/protostream/ProcessInstanceMarshaller.java
@@ -55,6 +55,7 @@ public class ProcessInstanceMarshaller extends AbstractMarshaller implements Mes
protected static final String MILESTONES = "milestones";
protected static final String CREATED_BY = "createdBy";
protected static final String UPDATED_BY = "updatedBy";
+ protected static final String SLA_DUE_DATE = "slaDueDate";
public ProcessInstanceMarshaller(ObjectMapper mapper) {
super(mapper);
@@ -84,6 +85,7 @@ public ProcessInstance readFrom(ProtoStreamReader reader) throws IOException {
pi.setVersion(reader.readString(VERSION));
pi.setCreatedBy(reader.readString(CREATED_BY));
pi.setUpdatedBy(reader.readString(UPDATED_BY));
+ pi.setSlaDueDate(dateToZonedDateTime(reader.readDate(SLA_DUE_DATE)));
return pi;
}
@@ -110,6 +112,7 @@ public void writeTo(ProtoStreamWriter writer, ProcessInstance pi) throws IOExcep
writer.writeString(VERSION, pi.getVersion());
writer.writeString(CREATED_BY, pi.getCreatedBy());
writer.writeString(UPDATED_BY, pi.getCreatedBy());
+ writer.writeDate(SLA_DUE_DATE, zonedDateTimeToDate(pi.getSlaDueDate()));
}
@Override
diff --git a/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/NodeInstanceEntity.java b/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/NodeInstanceEntity.java
index 347e6f9a7f..51c5bef912 100644
--- a/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/NodeInstanceEntity.java
+++ b/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/NodeInstanceEntity.java
@@ -43,6 +43,7 @@ public class NodeInstanceEntity extends AbstractEntity {
private String type;
private ZonedDateTime enter;
private ZonedDateTime exit;
+ private ZonedDateTime slaDueDate;
private String definitionId;
@ManyToOne(cascade = CascadeType.ALL, optional = false)
@OnDelete(action = OnDeleteAction.CASCADE)
@@ -106,6 +107,14 @@ public void setExit(ZonedDateTime exit) {
this.exit = exit;
}
+ public ZonedDateTime getSlaDueDate() {
+ return slaDueDate;
+ }
+
+ public void setSlaDueDate(ZonedDateTime slaDueDate) {
+ this.slaDueDate = slaDueDate;
+ }
+
public ProcessInstanceEntity getProcessInstance() {
return processInstance;
}
diff --git a/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/ProcessInstanceEntity.java b/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/ProcessInstanceEntity.java
index 7046de267b..a3a0b0ceb3 100644
--- a/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/ProcessInstanceEntity.java
+++ b/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/model/ProcessInstanceEntity.java
@@ -68,6 +68,9 @@ public class ProcessInstanceEntity extends AbstractEntity {
private String createdBy;
private String updatedBy;
+
+ private ZonedDateTime slaDueDate;
+
@Convert(converter = JsonBinaryConverter.class)
@Column(columnDefinition = "jsonb")
private ObjectNode variables;
@@ -203,6 +206,14 @@ public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
+ public ZonedDateTime getSlaDueDate() {
+ return slaDueDate;
+ }
+
+ public void setSlaDueDate(ZonedDateTime slaDueDate) {
+ this.slaDueDate = slaDueDate;
+ }
+
public ObjectNode getVariables() {
return variables;
}
@@ -286,6 +297,7 @@ public String toString() {
", lastUpdate=" + lastUpdate +
", createdBy=" + createdBy +
", updatedBy=" + updatedBy +
+ ", slaDueDate=" + slaDueDate +
", variables=" + variables +
", nodes=" + nodes +
", milestones=" + milestones +
diff --git a/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/ProcessInstanceEntityStorage.java b/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/ProcessInstanceEntityStorage.java
index 8796f3204a..68e5d24844 100644
--- a/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/ProcessInstanceEntityStorage.java
+++ b/data-index/data-index-storage/data-index-storage-jpa-common/src/main/java/org/kie/kogito/index/jpa/storage/ProcessInstanceEntityStorage.java
@@ -179,6 +179,7 @@ private NodeInstanceEntity updateNode(NodeInstanceEntity nodeInstance, ProcessIn
nodeInstance.setNodeId(body.getNodeDefinitionId());
nodeInstance.setName(body.getNodeName());
nodeInstance.setType(body.getNodeType());
+ nodeInstance.setSlaDueDate(toZonedDateTime(body.getSlaDueDate()));
ZonedDateTime eventDate = toZonedDateTime(body.getEventDate());
switch (body.getEventType()) {
case EVENT_TYPE_ENTER:
@@ -219,6 +220,7 @@ private void indexState(ProcessInstanceEntity pi, ProcessInstanceStateEventBody
pi.setLastUpdate(toZonedDateTime(data.getEventDate()));
pi.setAddons(addons);
pi.setEndpoint(endpoint);
+ pi.setSlaDueDate(toZonedDateTime(data.getSlaDueDate()));
}
private void indexVariable(ProcessInstanceEntity pi, ProcessInstanceVariableEventBody data) {
diff --git a/data-index/data-index-storage/data-index-storage-jpa-common/src/test/java/org/kie/kogito/index/jpa/storage/AbstractProcessInstanceStorageIT.java b/data-index/data-index-storage/data-index-storage-jpa-common/src/test/java/org/kie/kogito/index/jpa/storage/AbstractProcessInstanceStorageIT.java
index b60f7ed300..f8f8c6674e 100644
--- a/data-index/data-index-storage/data-index-storage-jpa-common/src/test/java/org/kie/kogito/index/jpa/storage/AbstractProcessInstanceStorageIT.java
+++ b/data-index/data-index-storage/data-index-storage-jpa-common/src/test/java/org/kie/kogito/index/jpa/storage/AbstractProcessInstanceStorageIT.java
@@ -109,7 +109,7 @@ public void testProcessInstanceNodeEvent() {
.hasSize(1);
Assertions.assertThat(processInstance.getNodes().get(0))
- .hasNoNullFieldsOrPropertiesExcept("exit")
+ .hasNoNullFieldsOrPropertiesExcept("exit", "slaDueDate")
.hasFieldOrPropertyWithValue("name", "nodeName")
.hasFieldOrPropertyWithValue("type", "BoundaryEventNode")
.hasFieldOrPropertyWithValue("definitionId", nodeDefinitionId)
@@ -125,7 +125,7 @@ public void testProcessInstanceNodeEvent() {
.hasSize(1);
Assertions.assertThat(processInstance.getNodes().get(0))
- .hasNoNullFieldsOrProperties()
+ .hasNoNullFieldsOrPropertiesExcept("slaDueDate")
.hasFieldOrPropertyWithValue("name", "nodeName")
.hasFieldOrPropertyWithValue("type", "BoundaryEventNode")
.hasFieldOrPropertyWithValue("definitionId", nodeDefinitionId)
diff --git a/data-index/data-index-storage/data-index-storage-jpa/src/main/resources/kie-flyway/db/data-index/ansi/V1.45.0.6__add_sla_due_date_columns.sql b/data-index/data-index-storage/data-index-storage-jpa/src/main/resources/kie-flyway/db/data-index/ansi/V1.45.0.6__add_sla_due_date_columns.sql
new file mode 100644
index 0000000000..fdd7838f41
--- /dev/null
+++ b/data-index/data-index-storage/data-index-storage-jpa/src/main/resources/kie-flyway/db/data-index/ansi/V1.45.0.6__add_sla_due_date_columns.sql
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+ALTER TABLE processes ADD sla_due_date timestamp;
+ALTER TABLE nodes ADD sla_due_date timestamp;
\ No newline at end of file
diff --git a/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntity.java b/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntity.java
index 28cef62442..5a66e6f298 100644
--- a/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntity.java
+++ b/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntity.java
@@ -70,6 +70,8 @@ public class ProcessInstanceEntity {
String updatedBy;
+ Long slaDueDate;
+
public String getId() {
return id;
}
@@ -238,6 +240,14 @@ public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
+ public Long getSlaDueDate() {
+ return slaDueDate;
+ }
+
+ public void setSlaDueDate(Long slaDueDate) {
+ this.slaDueDate = slaDueDate;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -271,6 +281,8 @@ public static class NodeInstanceEntity {
String definitionId;
+ Long slaDueDate;
+
public String getId() {
return id;
}
@@ -327,6 +339,14 @@ public void setDefinitionId(String definitionId) {
this.definitionId = definitionId;
}
+ public Long getSlaDueDate() {
+ return slaDueDate;
+ }
+
+ public void setSlaDueDate(Long slaDueDate) {
+ this.slaDueDate = slaDueDate;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntityMapper.java b/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntityMapper.java
index 16e1f13d3c..18e674d57e 100644
--- a/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntityMapper.java
+++ b/data-index/data-index-storage/data-index-storage-mongodb/src/main/java/org/kie/kogito/index/mongodb/model/ProcessInstanceEntityMapper.java
@@ -77,6 +77,7 @@ public ProcessInstanceEntity mapToEntity(String key, ProcessInstance instance) {
entity.setVersion(instance.getVersion());
entity.setCreatedBy(instance.getCreatedBy());
entity.setUpdatedBy(instance.getUpdatedBy());
+ entity.setSlaDueDate(zonedDateTimeToInstant(instance.getSlaDueDate()));
return entity;
}
@@ -108,6 +109,7 @@ public ProcessInstance mapToModel(ProcessInstanceEntity entity) {
instance.setVersion(entity.getVersion());
instance.setCreatedBy(entity.getCreatedBy());
instance.setUpdatedBy(entity.getCreatedBy());
+ instance.setSlaDueDate(instantToZonedDateTime(entity.getSlaDueDate()));
return instance;
}
@@ -146,6 +148,7 @@ NodeInstance toNodeInstance(ProcessInstanceEntity.NodeInstanceEntity entity) {
instance.setEnter(instantToZonedDateTime(entity.getEnter()));
instance.setExit(instantToZonedDateTime(entity.getExit()));
instance.setDefinitionId(entity.getDefinitionId());
+ instance.setSlaDueDate(instantToZonedDateTime(entity.getSlaDueDate()));
return instance;
}
@@ -162,6 +165,7 @@ ProcessInstanceEntity.NodeInstanceEntity fromNodeInstance(NodeInstance instance)
entity.setEnter(zonedDateTimeToInstant(instance.getEnter()));
entity.setExit(zonedDateTimeToInstant(instance.getExit()));
entity.setDefinitionId(instance.getDefinitionId());
+ entity.setSlaDueDate(zonedDateTimeToInstant(instance.getSlaDueDate()));
return entity;
}
diff --git a/data-index/data-index-storage/data-index-storage-postgresql/src/main/resources/kie-flyway/db/data-index/postgresql/V1.45.0.6__add_sla_due_date_columns.sql b/data-index/data-index-storage/data-index-storage-postgresql/src/main/resources/kie-flyway/db/data-index/postgresql/V1.45.0.6__add_sla_due_date_columns.sql
new file mode 100644
index 0000000000..58b83a3266
--- /dev/null
+++ b/data-index/data-index-storage/data-index-storage-postgresql/src/main/resources/kie-flyway/db/data-index/postgresql/V1.45.0.6__add_sla_due_date_columns.sql
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+ALTER TABLE IF exists processes ADD COLUMN IF NOT EXISTS sla_due_date timestamp;
+ALTER TABLE IF exists nodes ADD COLUMN IF NOT EXISTS sla_due_date timestamp;
\ No newline at end of file
diff --git a/data-index/data-index-storage/data-index-storage-protobuf/src/main/resources/META-INF/kogito-index.proto b/data-index/data-index-storage/data-index-storage-protobuf/src/main/resources/META-INF/kogito-index.proto
index 5c23eecefa..ed6d7c09ee 100644
--- a/data-index/data-index-storage/data-index-storage-protobuf/src/main/resources/META-INF/kogito-index.proto
+++ b/data-index/data-index-storage/data-index-storage-protobuf/src/main/resources/META-INF/kogito-index.proto
@@ -153,6 +153,7 @@ message ProcessInstance {
optional string createdBy = 20;
/* @Field(store = Store.YES) */
optional string updatedBy = 21;
+ optional int64 slaDueDate = 22;
}
/* @Indexed */
@@ -177,6 +178,7 @@ message NodeInstance {
optional string definitionId = 6;
/* @Field(store = Store.YES) */
optional string nodeId = 7;
+ optional int64 slaDueDate = 8;
}
/* @Indexed */
diff --git a/data-index/kogito-addons-quarkus-data-index-persistence/kogito-addons-quarkus-data-index-persistence-common/runtime/src/main/java/org/kie/kogito/index/addon/api/KogitoAddonRuntimeClientImpl.java b/data-index/kogito-addons-quarkus-data-index-persistence/kogito-addons-quarkus-data-index-persistence-common/runtime/src/main/java/org/kie/kogito/index/addon/api/KogitoAddonRuntimeClientImpl.java
index 697dcfd1e0..1f9b64d91d 100644
--- a/data-index/kogito-addons-quarkus-data-index-persistence/kogito-addons-quarkus-data-index-persistence-common/runtime/src/main/java/org/kie/kogito/index/addon/api/KogitoAddonRuntimeClientImpl.java
+++ b/data-index/kogito-addons-quarkus-data-index-persistence/kogito-addons-quarkus-data-index-persistence-common/runtime/src/main/java/org/kie/kogito/index/addon/api/KogitoAddonRuntimeClientImpl.java
@@ -130,7 +130,8 @@ public CompletableFuture getProcessInstanceDiagram(String serviceURL, Pr
if (processSvgService == null) {
return CompletableFuture.completedFuture(null);
} else {
- return CompletableFuture.supplyAsync(() -> processSvgService.getProcessInstanceSvg(processInstance.getProcessId(), processInstance.getId(), null).orElse(null), managedExecutor);
+ return CompletableFuture.supplyAsync(() -> processSvgService.getProcessInstanceSvg(processInstance.getProcessId(), processInstance.getId(), this.getAuthHeader()).orElse(null),
+ managedExecutor);
}
}
diff --git a/explainability/explainability-service-rest/pom.xml b/explainability/explainability-service-rest/pom.xml
index 6f0e7f1d0f..cb1f027812 100644
--- a/explainability/explainability-service-rest/pom.xml
+++ b/explainability/explainability-service-rest/pom.xml
@@ -86,11 +86,6 @@
kogito-quarkus-test-utils
test
-
- org.keycloak
- keycloak-core
- test
-
diff --git a/explainability/explainability-service-rest/src/test/java/org/kie/kogito/explainability/rest/KeycloakExplainabilityServiceIT.java b/explainability/explainability-service-rest/src/test/java/org/kie/kogito/explainability/rest/KeycloakExplainabilityServiceIT.java
index ee532e9153..d014777d8f 100644
--- a/explainability/explainability-service-rest/src/test/java/org/kie/kogito/explainability/rest/KeycloakExplainabilityServiceIT.java
+++ b/explainability/explainability-service-rest/src/test/java/org/kie/kogito/explainability/rest/KeycloakExplainabilityServiceIT.java
@@ -20,7 +20,6 @@
import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;
-import org.keycloak.representations.AccessTokenResponse;
import org.kie.kogito.test.quarkus.QuarkusTestProperty;
import org.kie.kogito.testcontainers.KogitoKeycloakContainer;
import org.kie.kogito.testcontainers.quarkus.KeycloakQuarkusTestResource;
@@ -65,6 +64,6 @@ private String getAccessToken(String userName) {
.param("client_secret", KogitoKeycloakContainer.CLIENT_SECRET)
.when()
.post(keycloakURL + "/protocol/openid-connect/token")
- .as(AccessTokenResponse.class).getToken();
+ .jsonPath().get("access_token");
}
}
diff --git a/jitexecutor/jitexecutor-dmn/pom.xml b/jitexecutor/jitexecutor-dmn/pom.xml
index f38b164c83..a2e705a419 100644
--- a/jitexecutor/jitexecutor-dmn/pom.xml
+++ b/jitexecutor/jitexecutor-dmn/pom.xml
@@ -121,6 +121,11 @@
assertj-core
test
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java
index 7c73c5eccc..54840c86b8 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java
@@ -22,11 +22,15 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
+import org.kie.api.builder.Message;
import org.kie.api.io.Resource;
import org.kie.dmn.api.core.DMNContext;
+import org.kie.dmn.api.core.DMNMessage;
import org.kie.dmn.api.core.DMNModel;
import org.kie.dmn.api.core.DMNResult;
import org.kie.dmn.api.core.DMNRuntime;
@@ -51,7 +55,43 @@ public static DMNEvaluator fromXML(String modelXML) {
.fromResources(Collections.singletonList(modelResource)).getOrElseThrow(RuntimeException::new);
dmnRuntime.addListener(new JITDMNListener());
DMNModel dmnModel = dmnRuntime.getModels().get(0);
- return new DMNEvaluator(dmnModel, dmnRuntime);
+ return validateForErrors(dmnModel, dmnRuntime);
+ }
+
+ public static DMNEvaluator fromMultiple(MultipleResourcesPayload payload) {
+ Map resources = new HashMap<>();
+ for (ResourceWithURI r : payload.getResources()) {
+ Resource readerResource = ResourceFactory.newReaderResource(new StringReader(r.getContent()), "UTF-8");
+ readerResource.setSourcePath(r.getURI());
+ resources.put(r.getURI(), readerResource);
+ }
+ ResolveByKey rbk = new ResolveByKey(resources);
+ DMNRuntime dmnRuntime = DMNRuntimeBuilder.fromDefaults()
+ .setRelativeImportResolver((x, y, locationURI) -> rbk.readerByKey(locationURI))
+ .buildConfiguration()
+ .fromResources(resources.values())
+ .getOrElseThrow(RuntimeException::new);
+ DMNModel mainModel = null;
+ for (DMNModel m : dmnRuntime.getModels()) {
+ if (m.getResource().getSourcePath().equals(payload.getMainURI())) {
+ mainModel = m;
+ break;
+ }
+ }
+ if (mainModel == null) {
+ throw new IllegalStateException("Was not able to identify main model from MultipleResourcesPayload contents.");
+ }
+ return validateForErrors(mainModel, dmnRuntime);
+ }
+
+ static DMNEvaluator validateForErrors(DMNModel dmnModel, DMNRuntime dmnRuntime) {
+ if (dmnModel.hasErrors()) {
+ List messages = dmnModel.getMessages(DMNMessage.Severity.ERROR);
+ String errorMessage = messages.stream().map(Message::getText).collect(Collectors.joining(", "));
+ throw new IllegalStateException(errorMessage);
+ } else {
+ return new DMNEvaluator(dmnModel, dmnRuntime);
+ }
}
private DMNEvaluator(DMNModel dmnModel, DMNRuntime dmnRuntime) {
@@ -88,29 +128,4 @@ public JITDMNResult evaluate(Map context) {
return new JITDMNResult(getNamespace(), getName(), dmnResult, evaluationHitIds.orElse(Collections.emptyMap()));
}
- public static DMNEvaluator fromMultiple(MultipleResourcesPayload payload) {
- Map resources = new HashMap<>();
- for (ResourceWithURI r : payload.getResources()) {
- Resource readerResource = ResourceFactory.newReaderResource(new StringReader(r.getContent()), "UTF-8");
- readerResource.setSourcePath(r.getURI());
- resources.put(r.getURI(), readerResource);
- }
- ResolveByKey rbk = new ResolveByKey(resources);
- DMNRuntime dmnRuntime = DMNRuntimeBuilder.fromDefaults()
- .setRelativeImportResolver((x, y, locationURI) -> rbk.readerByKey(locationURI))
- .buildConfiguration()
- .fromResources(resources.values())
- .getOrElseThrow(RuntimeException::new);
- DMNModel mainModel = null;
- for (DMNModel m : dmnRuntime.getModels()) {
- if (m.getResource().getSourcePath().equals(payload.getMainURI())) {
- mainModel = m;
- break;
- }
- }
- if (mainModel == null) {
- throw new IllegalStateException("Was not able to identify main model from MultipleResourcesPayload contents.");
- }
- return new DMNEvaluator(mainModel, dmnRuntime);
- }
}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/DMNResourceHelper.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/DMNResourceHelper.java
new file mode 100644
index 0000000000..b06064acc2
--- /dev/null
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/DMNResourceHelper.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.jitexecutor.dmn.api;
+
+import java.util.function.Supplier;
+
+import jakarta.ws.rs.core.Response;
+
+public class DMNResourceHelper {
+
+ private DMNResourceHelper() {
+ }
+
+ public static Response manageResponse(Supplier responseSupplier) {
+ try {
+ return responseSupplier.get();
+ } catch (Exception e) {
+ String errorMessage = e.getMessage() != null ? e.getMessage() : "Failed to get result due to " + e.getClass().getName();
+ return Response.status(Response.Status.BAD_REQUEST).entity(errorMessage).build();
+ }
+ }
+}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResource.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResource.java
index 69d4eb8b87..19afd5c2e7 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResource.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResource.java
@@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.function.Supplier;
import org.kie.dmn.core.internal.utils.MarshallingStubUtils;
import org.kie.kogito.jitexecutor.dmn.JITDMNService;
@@ -56,12 +57,15 @@ public Response jitdmn(JITDMNPayload payload) {
LOGGER.debug("jitdmn/");
LOGGER.debug(payload.toString());
LOGGER.debug(LINEBREAK);
- JITDMNResult evaluateAll = payload.getModel() != null ? jitdmnService.evaluateModel(payload.getModel(), payload.getContext()) : jitdmnService.evaluateModel(payload, payload.getContext());
- Map restResulk = new HashMap<>();
- for (Entry kv : evaluateAll.getContext().getAll().entrySet()) {
- restResulk.put(kv.getKey(), MarshallingStubUtils.stubDMNResult(kv.getValue(), String::valueOf));
- }
- return Response.ok(restResulk).build();
+ Supplier supplier = () -> {
+ JITDMNResult evaluateAll = payload.getModel() != null ? jitdmnService.evaluateModel(payload.getModel(), payload.getContext()) : jitdmnService.evaluateModel(payload, payload.getContext());
+ Map restResulk = new HashMap<>();
+ for (Entry kv : evaluateAll.getContext().getAll().entrySet()) {
+ restResulk.put(kv.getKey(), MarshallingStubUtils.stubDMNResult(kv.getValue(), String::valueOf));
+ }
+ return Response.ok(restResulk).build();
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
@POST
@@ -73,8 +77,11 @@ public Response jitdmnResult(JITDMNPayload payload) {
LOGGER.debug("jitdmn/dmnresult");
LOGGER.debug(payload.toString());
LOGGER.debug(LINEBREAK);
- JITDMNResult dmnResult = payload.getModel() != null ? jitdmnService.evaluateModel(payload.getModel(), payload.getContext()) : jitdmnService.evaluateModel(payload, payload.getContext());
- return Response.ok(dmnResult).build();
+ Supplier supplier = () -> {
+ JITDMNResult dmnResult = payload.getModel() != null ? jitdmnService.evaluateModel(payload.getModel(), payload.getContext()) : jitdmnService.evaluateModel(payload, payload.getContext());
+ return Response.ok(dmnResult).build();
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
@POST
@@ -86,9 +93,12 @@ public Response jitEvaluateAndExplain(JITDMNPayload payload) {
LOGGER.debug("jitdmn/evaluateAndExplain");
LOGGER.debug(payload.toString());
LOGGER.debug(LINEBREAK);
- DMNResultWithExplanation response =
- payload.getModel() != null ? jitdmnService.evaluateModelAndExplain(payload.getModel(), payload.getContext()) : jitdmnService.evaluateModelAndExplain(payload, payload.getContext());
- return Response.ok(response).build();
+ Supplier supplier = () -> {
+ DMNResultWithExplanation response =
+ payload.getModel() != null ? jitdmnService.evaluateModelAndExplain(payload.getModel(), payload.getContext()) : jitdmnService.evaluateModelAndExplain(payload, payload.getContext());
+ return Response.ok(response).build();
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResource.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResource.java
index b1ce72029c..674cff40b2 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResource.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResource.java
@@ -21,6 +21,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
import org.eclipse.microprofile.openapi.OASFactory;
import org.eclipse.microprofile.openapi.models.OpenAPI;
@@ -75,9 +76,12 @@ public Response schema(String payload) {
LOGGER.debug("jitdmn/validate");
LOGGER.debug(payload);
LOGGER.debug(LINEBREAK);
- DMNModel dmnModel = DMNEvaluator.fromXML(payload).getDmnModel();
- DMNOASResult oasResult = DMNOASGeneratorFactory.generator(Collections.singletonList(dmnModel)).build();
- return fullSchema(dmnModel, oasResult, true);
+ Supplier supplier = () -> {
+ DMNModel dmnModel = DMNEvaluator.fromXML(payload).getDmnModel();
+ DMNOASResult oasResult = DMNOASGeneratorFactory.generator(Collections.singletonList(dmnModel)).build();
+ return fullSchema(dmnModel, oasResult, true);
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
private Response fullSchema(DMNModel dmnModel, DMNOASResult oasResult, final boolean singleModel) {
@@ -111,10 +115,13 @@ private Response fullSchema(DMNModel dmnModel, DMNOASResult oasResult, final boo
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response schema(MultipleResourcesPayload payload) {
- DMNEvaluator dmnEvaluator = DMNEvaluator.fromMultiple(payload);
- DMNModel dmnModel = dmnEvaluator.getDmnModel();
- DMNOASResult oasResult = DMNOASGeneratorFactory.generator(dmnEvaluator.getAllDMNModels()).build();
- return fullSchema(dmnModel, oasResult, false);
+ Supplier supplier = () -> {
+ DMNEvaluator dmnEvaluator = DMNEvaluator.fromMultiple(payload);
+ DMNModel dmnModel = dmnEvaluator.getDmnModel();
+ DMNOASResult oasResult = DMNOASGeneratorFactory.generator(dmnEvaluator.getAllDMNModels()).build();
+ return fullSchema(dmnModel, oasResult, false);
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
@POST
@@ -122,9 +129,12 @@ public Response schema(MultipleResourcesPayload payload) {
@Produces(MediaType.APPLICATION_JSON)
@Path("form")
public Response form(String payload) {
- DMNModel dmnModel = DMNEvaluator.fromXML(payload).getDmnModel();
- DMNOASResult oasResult = DMNOASGeneratorFactory.generator(Collections.singletonList(dmnModel)).build();
- return formSchema(dmnModel, oasResult);
+ Supplier supplier = () -> {
+ DMNModel dmnModel = DMNEvaluator.fromXML(payload).getDmnModel();
+ DMNOASResult oasResult = DMNOASGeneratorFactory.generator(Collections.singletonList(dmnModel)).build();
+ return formSchema(dmnModel, oasResult);
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
@POST
@@ -132,10 +142,13 @@ public Response form(String payload) {
@Produces(MediaType.APPLICATION_JSON)
@Path("form")
public Response form(MultipleResourcesPayload payload) {
- DMNEvaluator dmnEvaluator = DMNEvaluator.fromMultiple(payload);
- DMNModel dmnModel = dmnEvaluator.getDmnModel();
- DMNOASResult oasResult = DMNOASGeneratorFactory.generator(dmnEvaluator.getAllDMNModels()).build();
- return formSchema(dmnModel, oasResult);
+ Supplier supplier = () -> {
+ DMNEvaluator dmnEvaluator = DMNEvaluator.fromMultiple(payload);
+ DMNModel dmnModel = dmnEvaluator.getDmnModel();
+ DMNOASResult oasResult = DMNOASGeneratorFactory.generator(dmnEvaluator.getAllDMNModels()).build();
+ return formSchema(dmnModel, oasResult);
+ };
+ return DMNResourceHelper.manageResponse(supplier);
}
private Response formSchema(DMNModel dmnModel, DMNOASResult oasResult) {
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluatorTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluatorTest.java
new file mode 100644
index 0000000000..71a5edb1a7
--- /dev/null
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluatorTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.jitexecutor.dmn;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.kie.dmn.api.core.DMNMessage;
+import org.kie.dmn.api.core.DMNModel;
+import org.kie.dmn.api.core.DMNRuntime;
+import org.kie.dmn.core.impl.DMNRuntimeImpl;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.kie.kogito.jitexecutor.dmn.TestingUtils.getModelFromIoUtils;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DMNEvaluatorTest {
+
+ private static String model;
+ private static String invalidModel;
+
+ @BeforeAll
+ public static void setup() throws IOException {
+ model = getModelFromIoUtils("invalid_models/DMNv1_x/test.dmn");
+ invalidModel = getModelFromIoUtils("invalid_models/DMNv1_5/DMN-Invalid.dmn");
+ }
+
+ @Test
+ void testFromXMLSuccessModel() {
+ String modelXML = model;
+
+ DMNEvaluator evaluator = DMNEvaluator.fromXML(modelXML);
+ assertNotNull(evaluator);
+ }
+
+ @Test
+ public void testFromXMLModelWithError() {
+ String modelXML = invalidModel;
+
+ assertThrows(IllegalStateException.class, () -> {
+ DMNEvaluator.fromXML(modelXML);
+ });
+ }
+
+ @Test
+ void testValidateForErrorsThrowsException() {
+ DMNModel dmnModel = mock(DMNModel.class);
+ DMNRuntime dmnRuntime = mock(DMNRuntime.class);
+ DMNMessage message = mock(DMNMessage.class);
+
+ String errorMessage = "Error compiling FEEL expression 'Person Age >= 18' for name 'Can Drive?' on node 'Can Drive?': syntax error near 'Age'";
+ when(message.getText()).thenReturn(errorMessage);
+ when(dmnModel.hasErrors()).thenReturn(true);
+ when(dmnModel.getMessages(DMNMessage.Severity.ERROR)).thenReturn(Collections.singletonList(message));
+
+ assertThrows(IllegalStateException.class,
+ () -> DMNEvaluator.validateForErrors(dmnModel, dmnRuntime), errorMessage);
+ }
+
+ @Test
+ void testValidateForErrors() {
+ DMNModel dmnModel = mock(DMNModel.class);
+ DMNRuntime dmnRuntime = mock(DMNRuntimeImpl.class);
+
+ when(dmnModel.hasErrors()).thenReturn(false);
+ DMNEvaluator evaluator = DMNEvaluator.validateForErrors(dmnModel, dmnRuntime);
+
+ assertNotNull(evaluator);
+ }
+
+}
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/DMNResourceHelperTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/DMNResourceHelperTest.java
new file mode 100644
index 0000000000..bd6ee56291
--- /dev/null
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/DMNResourceHelperTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.jitexecutor.dmn;
+
+import java.util.function.Supplier;
+
+import org.junit.jupiter.api.Test;
+import org.kie.kogito.jitexecutor.dmn.api.DMNResourceHelper;
+
+import jakarta.ws.rs.core.Response;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DMNResourceHelperTest {
+
+ @Test
+ public void testManageResponseWithSuccess() {
+ Supplier responseSupplier = () -> Response.ok("Success").build();
+ try (Response response = DMNResourceHelper.manageResponse(responseSupplier)) {
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals("Success", response.getEntity());
+ }
+
+ }
+
+ @Test
+ public void testManageResponseWithFailure() {
+ Supplier responseSupplier = mock(Supplier.class);
+ when(responseSupplier.get()).thenThrow(new IllegalStateException("Error : Failed to validate"));
+ try (Response response = DMNResourceHelper.manageResponse(responseSupplier)) {
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+ assertEquals("Error : Failed to validate", response.getEntity());
+ }
+
+ }
+
+}
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/TestingUtils.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/TestingUtils.java
index 257b0b4664..f83e0a805a 100644
--- a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/TestingUtils.java
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/TestingUtils.java
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -7,7 +7,7 @@
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java
index cacf238916..99634d4d59 100644
--- a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java
@@ -46,6 +46,7 @@
@QuarkusTest
public class JITDMNResourceTest {
+ private static String model;
private static String invalidModel;
private static String modelWithExtensionElements;
private static String modelWithMultipleEvaluationHitIds;
@@ -60,14 +61,15 @@ public class JITDMNResourceTest {
@BeforeAll
public static void setup() throws IOException {
- invalidModel = getModelFromIoUtils("invalid_models/DMNv1_x/test.dmn");
+ model = getModelFromIoUtils("invalid_models/DMNv1_x/test.dmn");
+ invalidModel = getModelFromIoUtils("invalid_models/DMNv1_5/DMN-Invalid.dmn");
modelWithExtensionElements = getModelFromIoUtils("valid_models/DMNv1_x/testWithExtensionElements.dmn");
modelWithMultipleEvaluationHitIds = getModelFromIoUtils("valid_models/DMNv1_5/MultipleHitRules.dmn");
}
@Test
void testjitEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(model, buildContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -116,7 +118,7 @@ void testjitdmnResultEndpointWithEvaluationHitIds() throws JsonProcessingExcepti
@Test
void testjitExplainabilityEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(model, buildContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -143,6 +145,42 @@ void testjitdmnWithExtensionElements() {
.body(containsString("m"), containsString("n"), containsString("sum"));
}
+ @Test
+ void testjitEndpointFailure() {
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildContext());
+ given()
+ .contentType(ContentType.JSON)
+ .body(jitdmnpayload)
+ .when().post("/jitdmn")
+ .then()
+ .statusCode(400)
+ .body(containsString("Error compiling FEEL expression 'Person Age >= 18' for name 'Can Drive?' on node 'Can Drive?': syntax error near 'Age'"));
+ }
+
+ @Test
+ void testjitdmnEvaluateInvalidModel() {
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildInvalidModelContext());
+ given()
+ .contentType(ContentType.JSON)
+ .body(jitdmnpayload)
+ .when().post("/jitdmn/dmnresult")
+ .then()
+ .statusCode(400)
+ .body(containsString("Error compiling FEEL expression 'Person Age >= 18' for name 'Can Drive?' on node 'Can Drive?': syntax error near 'Age'"));
+ }
+
+ @Test
+ void testjitdmnEvaluateAndExplainInvalidModel() {
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildInvalidModelContext());
+ given()
+ .contentType(ContentType.JSON)
+ .body(jitdmnpayload)
+ .when().post("/jitdmn/evaluateAndExplain")
+ .then()
+ .statusCode(400)
+ .body(containsString("Error compiling FEEL expression 'Person Age >= 18' for name 'Can Drive?' on node 'Can Drive?': syntax error near 'Age'"));
+ }
+
private Map buildContext() {
Map context = new HashMap<>();
context.put("FICO Score", 800);
@@ -160,4 +198,12 @@ private Map buildMultipleHitContext() {
context.put("Numbers", numbers);
return context;
}
+
+ private Map buildInvalidModelContext() {
+ Map context = new HashMap<>();
+ context.put("Can Drive?", false);
+ context.put("Person Age", 14);
+ context.put("Id", 1);
+ return context;
+ }
}
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResourceTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResourceTest.java
index feb28be1c3..6cd22bd460 100644
--- a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResourceTest.java
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/SchemaResourceTest.java
@@ -43,4 +43,17 @@ public void test() throws IOException {
.statusCode(200)
.body(containsString("InputSet"), containsString("x-dmn-type"));
}
+
+ @Test
+ public void testJitDmnValidate() throws IOException {
+ final String MODEL = getModelFromIoUtils("invalid_models/DMNv1_5/DMN-Invalid.dmn");
+ given()
+ .contentType(ContentType.XML)
+ .body(MODEL)
+ .when().post("/jitdmn/schema")
+ .then()
+ .statusCode(400)
+ .body(containsString("Error compiling FEEL expression 'Person Age >= 18' for name 'Can Drive?' on node 'Can Drive?': syntax error near 'Age'"));
+
+ }
}
diff --git a/jobs-service/jobs-service-common/pom.xml b/jobs-service/jobs-service-common/pom.xml
index cdfc82a41a..6b19b74d56 100644
--- a/jobs-service/jobs-service-common/pom.xml
+++ b/jobs-service/jobs-service-common/pom.xml
@@ -163,11 +163,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-core
- test
-
org.mockito
mockito-junit-jupiter
diff --git a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JacksonConfiguration.java b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JacksonConfiguration.java
index cfbbd024a5..f1603c1ef4 100644
--- a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JacksonConfiguration.java
+++ b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JacksonConfiguration.java
@@ -20,7 +20,7 @@
import org.kie.kogito.jobs.DurationExpirationTime;
import org.kie.kogito.jobs.ExactExpirationTime;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.JobDescription;
import org.kie.kogito.jobs.service.api.serlialization.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,8 +46,8 @@ public ObjectMapperCustomizer customizer() {
return objectMapper -> {
LOGGER.debug("Jackson customization initialized.");
SimpleModule kogitoCustomModule = new SimpleModule();
- kogitoCustomModule.addSerializer(ProcessInstanceJobDescription.class, new ProcessInstanceJobDescriptionSerializer());
- kogitoCustomModule.addDeserializer(ProcessInstanceJobDescription.class, new ProcessInstanceJobDescriptionDeserializer());
+ kogitoCustomModule.addSerializer(JobDescription.class, new JobDescriptionSerializer());
+ kogitoCustomModule.addDeserializer(JobDescription.class, new JobDescriptionDeserializer());
kogitoCustomModule.addSerializer(DurationExpirationTime.class, new DurationExpirationTimeSerializer());
kogitoCustomModule.addDeserializer(DurationExpirationTime.class, new DurationExpirationTimeDeserializer());
kogitoCustomModule.addSerializer(ExactExpirationTime.class, new ExactExpirationTimeSerializer());
diff --git a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JobDescriptionDeserializer.java b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JobDescriptionDeserializer.java
new file mode 100644
index 0000000000..f0a72db2b4
--- /dev/null
+++ b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JobDescriptionDeserializer.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.jobs.service.json;
+
+import java.io.IOException;
+
+import org.kie.kogito.jobs.ExpirationTime;
+import org.kie.kogito.jobs.JobDescription;
+import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescriptionBuilder;
+import org.kie.kogito.jobs.descriptors.UserTaskInstanceJobDescription;
+import org.kie.kogito.jobs.descriptors.UserTaskInstanceJobDescriptionBuilder;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+import static java.util.Optional.ofNullable;
+
+public class JobDescriptionDeserializer extends StdDeserializer {
+
+ private static final long serialVersionUID = -8307549297456060422L;
+
+ public JobDescriptionDeserializer() {
+ super(ProcessInstanceJobDescription.class);
+ }
+
+ @Override
+ public JobDescription deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException {
+ try {
+ JsonNode node = jp.getCodec().readTree(jp);
+ String jobDescriptionType = node.get("@type").asText();
+ switch (jobDescriptionType) {
+ case "ProcessInstanceJobDescription": {
+ ProcessInstanceJobDescriptionBuilder builder = ProcessInstanceJobDescription.newProcessInstanceJobDescriptionBuilder();
+ ofNullable(node.get("id")).ifPresent(e -> builder.id(e.textValue()));
+ ofNullable(node.get("priority")).ifPresent(e -> builder.priority(e.asInt()));
+ String expirationTimeType = node.get("expirationTime").get("@type").asText();
+ builder.expirationTime((ExpirationTime) ctxt.readTreeAsValue(node.get("expirationTime"), Class.forName(expirationTimeType)));
+
+ ofNullable(node.get("timerId")).ifPresent(e -> builder.timerId(e.textValue()));
+ ofNullable(node.get("processInstanceId")).ifPresent(e -> builder.processInstanceId(e.textValue()));
+ ofNullable(node.get("rootProcessInstanceId")).ifPresent(e -> builder.rootProcessInstanceId(e.textValue()));
+ ofNullable(node.get("processId")).ifPresent(e -> builder.processId(e.textValue()));
+ ofNullable(node.get("rootProcessId")).ifPresent(e -> builder.rootProcessId(e.textValue()));
+ ofNullable(node.get("nodeInstanceId")).ifPresent(e -> builder.nodeInstanceId(e.textValue()));
+
+ return builder.build();
+ }
+ case "UserTaskInstanceJobDescription": {
+ UserTaskInstanceJobDescriptionBuilder builder = UserTaskInstanceJobDescription.newUserTaskInstanceJobDescriptionBuilder();
+ ofNullable(node.get("id")).ifPresent(e -> builder.id(e.textValue()));
+ ofNullable(node.get("priority")).ifPresent(e -> builder.priority(e.asInt()));
+ String expirationTimeType = node.get("expirationTime").get("@type").asText();
+ builder.expirationTime((ExpirationTime) ctxt.readTreeAsValue(node.get("expirationTime"), Class.forName(expirationTimeType)));
+
+ ofNullable(node.get("userTaskInstanceId")).ifPresent(e -> builder.userTaskInstanceId(e.textValue()));
+ return builder.build();
+ }
+ }
+ } catch (ClassNotFoundException e1) {
+ throw new IllegalArgumentException("expiration time class not found", e1);
+ }
+ return null;
+ }
+
+}
diff --git a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/ProcessInstanceJobDescriptionSerializer.java b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JobDescriptionSerializer.java
similarity index 50%
rename from jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/ProcessInstanceJobDescriptionSerializer.java
rename to jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JobDescriptionSerializer.java
index 379da2a0e5..22935e0e37 100644
--- a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/ProcessInstanceJobDescriptionSerializer.java
+++ b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/JobDescriptionSerializer.java
@@ -20,32 +20,40 @@
import java.io.IOException;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.JobDescription;
+import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.descriptors.UserTaskInstanceJobDescription;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-public class ProcessInstanceJobDescriptionSerializer extends StdSerializer {
+public class JobDescriptionSerializer extends StdSerializer {
private static final long serialVersionUID = -8307549297456060422L;
- public ProcessInstanceJobDescriptionSerializer() {
- super(ProcessInstanceJobDescription.class);
+ public JobDescriptionSerializer() {
+ super(JobDescription.class);
}
@Override
- public void serialize(ProcessInstanceJobDescription value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
+ public void serialize(JobDescription value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeStartObject();
+ jgen.writeStringField("@type", value.getClass().getSimpleName());
jgen.writeStringField("id", value.id());
- jgen.writeStringField("timerId", value.timerId());
- jgen.writeObjectField("expirationTime", value.expirationTime());
jgen.writeNumberField("priority", value.priority());
- jgen.writeStringField("processInstanceId", value.processInstanceId());
- jgen.writeStringField("rootProcessInstanceId", value.rootProcessInstanceId());
- jgen.writeStringField("processId", value.processId());
- jgen.writeStringField("rootProcessId", value.rootProcessId());
- jgen.writeStringField("nodeInstanceId", value.nodeInstanceId());
+ jgen.writeObjectField("expirationTime", value.expirationTime());
+ if (value instanceof ProcessInstanceJobDescription jobDescription) {
+ jgen.writeStringField("timerId", jobDescription.timerId());
+ jgen.writeStringField("processInstanceId", jobDescription.processInstanceId());
+ jgen.writeStringField("rootProcessInstanceId", jobDescription.rootProcessInstanceId());
+ jgen.writeStringField("processId", jobDescription.processId());
+ jgen.writeStringField("rootProcessId", jobDescription.rootProcessId());
+ jgen.writeStringField("nodeInstanceId", jobDescription.nodeInstanceId());
+ jgen.writeEndObject();
+ } else if (value instanceof UserTaskInstanceJobDescription userTaskInstanceJobDescription) {
+ jgen.writeStringField("userTaskInstanceId", userTaskInstanceJobDescription.getUserTaskInstanceId());
+ }
jgen.writeEndObject();
}
diff --git a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/ProcessInstanceJobDescriptionDeserializer.java b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/ProcessInstanceJobDescriptionDeserializer.java
deleted file mode 100644
index 6ccfb99f47..0000000000
--- a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/json/ProcessInstanceJobDescriptionDeserializer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.kie.kogito.jobs.service.json;
-
-import java.io.IOException;
-
-import org.kie.kogito.jobs.ExpirationTime;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
-import org.kie.kogito.jobs.ProcessInstanceJobDescriptionBuilder;
-
-import com.fasterxml.jackson.core.JacksonException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-import static java.util.Optional.ofNullable;
-
-public class ProcessInstanceJobDescriptionDeserializer extends StdDeserializer {
-
- private static final long serialVersionUID = -8307549297456060422L;
-
- public ProcessInstanceJobDescriptionDeserializer() {
- super(ProcessInstanceJobDescription.class);
- }
-
- @Override
- public ProcessInstanceJobDescription deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException {
- ProcessInstanceJobDescriptionBuilder builder = ProcessInstanceJobDescription.builder();
-
- JsonNode node = jp.getCodec().readTree(jp);
- ofNullable(node.get("id")).ifPresent(e -> builder.id(e.textValue()));
- ofNullable(node.get("timerId")).ifPresent(e -> builder.timerId(e.textValue()));
- ofNullable(node.get("priority")).ifPresent(e -> builder.priority(e.asInt()));
- ofNullable(node.get("processInstanceId")).ifPresent(e -> builder.processInstanceId(e.textValue()));
- ofNullable(node.get("rootProcessInstanceId")).ifPresent(e -> builder.rootProcessInstanceId(e.textValue()));
- ofNullable(node.get("processId")).ifPresent(e -> builder.processId(e.textValue()));
- ofNullable(node.get("rootProcessId")).ifPresent(e -> builder.rootProcessId(e.textValue()));
- ofNullable(node.get("nodeInstanceId")).ifPresent(e -> builder.nodeInstanceId(e.textValue()));
-
- String type = node.get("expirationTime").get("@type").asText();
- try {
- builder.expirationTime((ExpirationTime) ctxt.readTreeAsValue(node.get("expirationTime"), Class.forName(type)));
- } catch (ClassNotFoundException | IOException e1) {
- e1.printStackTrace();
- }
-
- return builder.build();
- }
-
-}
diff --git a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/stream/AbstractJobStreams.java b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/stream/AbstractJobStreams.java
index 64189e2ab1..d09d3bbc5f 100644
--- a/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/stream/AbstractJobStreams.java
+++ b/jobs-service/jobs-service-common/src/main/java/org/kie/kogito/jobs/service/stream/AbstractJobStreams.java
@@ -65,16 +65,12 @@ public boolean isEnabled() {
public void jobStatusChange(JobDetails job) {
if (isEnabled()) {
try {
- JobDataEvent event = JobDataEvent
- .builder()
- .source(url + RestApiConstants.JOBS_PATH)
- .data(ScheduledJobAdapter.of(job))//this should support jobs crated with V1 and V2
- .build();
+ JobDataEvent event = buildEvent(job);
LOGGER.debug("emit jobStatusChange, hasRequests: {}, eventId: {}, jobDetails: {}", emitter.hasRequests(), event.getId(), job);
String json = objectMapper.writeValueAsString(event);
emitter.send(decorate(ContextAwareMessage.of(json)
.withAck(() -> onAck(event.getId(), job))
- .withNack(reason -> onNack(reason, job))));
+ .withNack(reason -> onNack(reason, job)), event));
} catch (Exception e) {
String msg = String.format("An unexpected error was produced while processing a Job status change for the job: %s", job);
LOGGER.error(msg, e);
@@ -82,6 +78,14 @@ public void jobStatusChange(JobDetails job) {
}
}
+ protected JobDataEvent buildEvent(JobDetails job) {
+ return JobDataEvent
+ .builder()
+ .source(url + RestApiConstants.JOBS_PATH)
+ .data(ScheduledJobAdapter.of(job))//this should support jobs crated with V1 and V2
+ .build();
+ }
+
protected CompletionStage onAck(String eventId, JobDetails job) {
LOGGER.debug("Job Status change emitted successfully, eventId: {}, jobDetails: {}", eventId, job);
return CompletableFuture.completedFuture(null);
@@ -93,7 +97,7 @@ protected CompletionStage onNack(Throwable reason, JobDetails job) {
return CompletableFuture.completedFuture(null);
}
- protected Message decorate(Message message) {
+ protected Message decorate(Message message, JobDataEvent event) {
return message;
}
}
diff --git a/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/resource/BaseKeycloakJobServiceTest.java b/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/resource/BaseKeycloakJobServiceTest.java
index 617efe207c..1a2d56764e 100644
--- a/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/resource/BaseKeycloakJobServiceTest.java
+++ b/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/resource/BaseKeycloakJobServiceTest.java
@@ -24,7 +24,6 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.keycloak.representations.AccessTokenResponse;
import org.kie.kogito.jobs.api.Job;
import org.kie.kogito.jobs.api.JobBuilder;
import org.kie.kogito.jobs.service.model.JobStatus;
@@ -234,6 +233,6 @@ private String getAccessToken(String userName) {
.param("client_secret", KogitoKeycloakContainer.CLIENT_SECRET)
.when()
.post(keycloakURL + "/protocol/openid-connect/token")
- .as(AccessTokenResponse.class).getToken();
+ .jsonPath().get("access_token");
}
}
diff --git a/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/stream/AbstractJobStreamsTest.java b/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/stream/AbstractJobStreamsTest.java
index f7ac6ed1ce..1f2e3fc33b 100644
--- a/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/stream/AbstractJobStreamsTest.java
+++ b/jobs-service/jobs-service-common/src/test/java/org/kie/kogito/jobs/service/stream/AbstractJobStreamsTest.java
@@ -58,7 +58,7 @@ public abstract class AbstractJobStreamsTest {
protected static final String URL = "http://localhost:8180";
private static final String SERIALIZED_MESSAGE = "SERIALIZED_MESSAGE";
- private static final String JOB_ID = "JOB_ID";
+ protected static final String JOB_ID = "JOB_ID";
private static final String CORRELATION_ID = "CORRELATION_ID";
private static final JobStatus STATUS = JobStatus.SCHEDULED;
private static final ZonedDateTime LAST_UPDATE = ZonedDateTime.parse("2022-08-03T18:00:15.001+01:00");
@@ -170,7 +170,7 @@ private JobDetails mockJobDetails() {
}
- private void assertExpectedEvent(JobDataEvent event) {
+ protected void assertExpectedEvent(JobDataEvent event) {
assertThat(event.getId()).isNotNull();
assertThat(event.getType()).isEqualTo(JobDataEvent.JOB_EVENT_TYPE);
assertThat(event.getSource()).hasToString(URL + "/jobs");
diff --git a/jobs-service/jobs-service-infinispan/pom.xml b/jobs-service/jobs-service-infinispan/pom.xml
index a5bfaed242..df8231b831 100644
--- a/jobs-service/jobs-service-infinispan/pom.xml
+++ b/jobs-service/jobs-service-infinispan/pom.xml
@@ -114,11 +114,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-core
- test
-
com.github.tomakehurst
wiremock-jre8
diff --git a/jobs-service/jobs-service-inmemory/pom.xml b/jobs-service/jobs-service-inmemory/pom.xml
index 70d047a98b..8ab200e963 100644
--- a/jobs-service/jobs-service-inmemory/pom.xml
+++ b/jobs-service/jobs-service-inmemory/pom.xml
@@ -107,11 +107,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-core
- test
-
com.github.tomakehurst
wiremock-jre8
diff --git a/jobs-service/jobs-service-messaging-http/src/main/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreams.java b/jobs-service/jobs-service-messaging-http/src/main/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreams.java
index 52bb50d35f..61a2efebaf 100644
--- a/jobs-service/jobs-service-messaging-http/src/main/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreams.java
+++ b/jobs-service/jobs-service-messaging-http/src/main/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreams.java
@@ -26,6 +26,7 @@
import org.eclipse.microprofile.reactive.messaging.Emitter;
import org.eclipse.microprofile.reactive.messaging.Message;
import org.eclipse.microprofile.reactive.messaging.OnOverflow;
+import org.kie.kogito.jobs.service.events.JobDataEvent;
import org.kie.kogito.jobs.service.model.JobDetails;
import org.kie.kogito.jobs.service.stream.AbstractJobStreams;
import org.slf4j.Logger;
@@ -45,6 +46,7 @@ public class HttpJobStreams extends AbstractJobStreams {
public static final String PUBLISH_EVENTS_CONFIG_KEY = "kogito.jobs-service.http.job-status-change-events";
public static final String JOB_STATUS_CHANGE_EVENTS_HTTP = "kogito-job-service-job-status-events-http";
+ public static final String PARTITION_KEY_EXTENSION = "partitionkey";
private static final Logger LOGGER = LoggerFactory.getLogger(HttpJobStreams.class);
@@ -70,7 +72,16 @@ public void jobStatusChange(JobDetails job) {
}
@Override
- protected Message decorate(Message message) {
+ protected JobDataEvent buildEvent(JobDetails job) {
+ JobDataEvent event = super.buildEvent(job);
+ // use the well-known extension https://github.com/cloudevents/spec/blob/main/cloudevents/extensions/partitioning.md
+ // to instruct potential http driven Brokers like, Knative Eventing Kafka Broker, to process accordingly.
+ event.addExtensionAttribute(PARTITION_KEY_EXTENSION, event.getData().getId());
+ return event;
+ }
+
+ @Override
+ protected Message decorate(Message message, JobDataEvent event) {
return message.addMetadata(OUTGOING_HTTP_METADATA.get());
}
}
diff --git a/jobs-service/jobs-service-messaging-http/src/test/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreamsTest.java b/jobs-service/jobs-service-messaging-http/src/test/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreamsTest.java
index 8449d88da6..7b951b5e39 100644
--- a/jobs-service/jobs-service-messaging-http/src/test/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreamsTest.java
+++ b/jobs-service/jobs-service-messaging-http/src/test/java/org/kie/kogito/jobs/service/messaging/http/stream/HttpJobStreamsTest.java
@@ -21,6 +21,7 @@
import java.util.Optional;
import org.eclipse.microprofile.reactive.messaging.Message;
+import org.kie.kogito.jobs.service.events.JobDataEvent;
import org.kie.kogito.jobs.service.stream.AbstractJobStreamsTest;
import io.cloudevents.jackson.JsonFormat;
@@ -29,6 +30,7 @@
import jakarta.ws.rs.core.HttpHeaders;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.kie.kogito.jobs.service.messaging.http.stream.HttpJobStreams.PARTITION_KEY_EXTENSION;
class HttpJobStreamsTest extends AbstractJobStreamsTest {
@@ -44,4 +46,12 @@ protected void assertExpectedMetadata(Message message) {
assertThat(metadata.getHeaders()).hasSize(1);
assertThat(metadata.getHeaders().get(HttpHeaders.CONTENT_TYPE)).containsExactlyInAnyOrder(JsonFormat.CONTENT_TYPE);
}
+
+ @Override
+ protected void assertExpectedEvent(JobDataEvent event) {
+ super.assertExpectedEvent(event);
+ assertThat(event.getExtension(PARTITION_KEY_EXTENSION))
+ .isNotNull()
+ .isEqualTo(JOB_ID);
+ }
}
diff --git a/jobs-service/jobs-service-messaging-kafka/src/main/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreams.java b/jobs-service/jobs-service-messaging-kafka/src/main/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreams.java
index c9b149ede2..315d89dff4 100644
--- a/jobs-service/jobs-service-messaging-kafka/src/main/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreams.java
+++ b/jobs-service/jobs-service-messaging-kafka/src/main/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreams.java
@@ -23,7 +23,9 @@
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.eclipse.microprofile.reactive.messaging.Emitter;
+import org.eclipse.microprofile.reactive.messaging.Message;
import org.eclipse.microprofile.reactive.messaging.OnOverflow;
+import org.kie.kogito.jobs.service.events.JobDataEvent;
import org.kie.kogito.jobs.service.model.JobDetails;
import org.kie.kogito.jobs.service.stream.AbstractJobStreams;
import org.kie.kogito.jobs.service.stream.AvailableStreams;
@@ -32,6 +34,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
+import io.smallrye.reactive.messaging.kafka.api.OutgoingKafkaRecordMetadata;
+
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@@ -54,4 +58,10 @@ public void jobStatusChange(JobDetails job) {
LOGGER.debug("jobStatusChange call received, enabled: {}, job: {}", enabled, job);
super.jobStatusChange(job);
}
+
+ @Override
+ protected Message decorate(Message message, JobDataEvent event) {
+ // regular kafka partitioning.
+ return message.addMetadata(OutgoingKafkaRecordMetadata.builder().withKey(event.getData().getId()).build());
+ }
}
diff --git a/jobs-service/jobs-service-messaging-kafka/src/test/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreamsTest.java b/jobs-service/jobs-service-messaging-kafka/src/test/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreamsTest.java
index a0dbc6c95d..d5be8d1f5f 100644
--- a/jobs-service/jobs-service-messaging-kafka/src/test/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreamsTest.java
+++ b/jobs-service/jobs-service-messaging-kafka/src/test/java/org/kie/kogito/jobs/service/messaging/kafka/stream/KafkaJobStreamsTest.java
@@ -20,12 +20,24 @@
import java.util.Optional;
+import org.eclipse.microprofile.reactive.messaging.Message;
import org.kie.kogito.jobs.service.stream.AbstractJobStreamsTest;
+import io.smallrye.reactive.messaging.kafka.api.OutgoingKafkaRecordMetadata;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
class KafkaJobStreamsTest extends AbstractJobStreamsTest {
@Override
protected KafkaJobStreams createJobStreams() {
return new KafkaJobStreams(objectMapper, Optional.of(true), emitter, URL);
}
+
+ @Override
+ protected void assertExpectedMetadata(Message message) {
+ OutgoingKafkaRecordMetadata> metadata = message.getMetadata(OutgoingKafkaRecordMetadata.class).orElse(null);
+ assertThat(metadata).isNotNull();
+ assertThat(metadata.getKey()).isEqualTo(JOB_ID);
+ }
}
diff --git a/jobs-service/jobs-service-mongodb/pom.xml b/jobs-service/jobs-service-mongodb/pom.xml
index 3830fcb196..45018a9d47 100644
--- a/jobs-service/jobs-service-mongodb/pom.xml
+++ b/jobs-service/jobs-service-mongodb/pom.xml
@@ -101,11 +101,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-core
- test
-
com.github.tomakehurst
wiremock-jre8
diff --git a/jobs-service/jobs-service-postgresql-common/pom.xml b/jobs-service/jobs-service-postgresql-common/pom.xml
index ab5b3eac63..a88b981d04 100644
--- a/jobs-service/jobs-service-postgresql-common/pom.xml
+++ b/jobs-service/jobs-service-postgresql-common/pom.xml
@@ -99,11 +99,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-core
- test
-
com.github.tomakehurst
wiremock-jre8
diff --git a/jobs-service/jobs-service-storage-jpa/pom.xml b/jobs-service/jobs-service-storage-jpa/pom.xml
index b49d36ce73..99de150744 100644
--- a/jobs-service/jobs-service-storage-jpa/pom.xml
+++ b/jobs-service/jobs-service-storage-jpa/pom.xml
@@ -113,11 +113,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-core
- test
-
com.github.tomakehurst
wiremock-jre8
diff --git a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobExecutor.java b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobExecutor.java
index ead3bbf2a2..961e0485aa 100644
--- a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobExecutor.java
+++ b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobExecutor.java
@@ -19,9 +19,13 @@
package org.kie.kogito.jobs.embedded;
import java.util.Optional;
+import java.util.function.Supplier;
import org.kie.kogito.Application;
import org.kie.kogito.Model;
+import org.kie.kogito.jobs.JobDescription;
+import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.descriptors.UserTaskInstanceJobDescription;
import org.kie.kogito.jobs.service.api.Recipient;
import org.kie.kogito.jobs.service.exception.JobExecutionException;
import org.kie.kogito.jobs.service.executor.JobExecutor;
@@ -31,40 +35,81 @@
import org.kie.kogito.process.Process;
import org.kie.kogito.process.Processes;
import org.kie.kogito.services.jobs.impl.TriggerJobCommand;
+import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.UserTasks;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Alternative;
+import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
+import static org.kie.kogito.services.uow.UnitOfWorkExecutor.executeInUnitOfWork;
+
@ApplicationScoped
@Alternative
public class EmbeddedJobExecutor implements JobExecutor {
@Inject
- Processes processes;
+ Instance processes;
+
+ @Inject
+ Instance userTasks;
@Inject
Application application;
@Override
public Uni execute(JobDetails jobDetails) {
-
- String correlationId = jobDetails.getCorrelationId();
RecipientInstance recipientModel = (RecipientInstance) jobDetails.getRecipient();
InVMRecipient recipient = (InVMRecipient) recipientModel.getRecipient();
- String timerId = recipient.getPayload().getData().timerId();
- String processInstanceId = recipient.getPayload().getData().processInstanceId();
- Optional> process;
- try {
- process = processes.processByProcessInstanceId(processInstanceId);
- } catch (Exception ex) {
- return Uni.createFrom().failure(
- new JobExecutionException(jobDetails.getId(),
- "Unexpected error when executing Embedded request for job: " + jobDetails.getId() + ". " + ex.getMessage(),
- ex));
+ JobDescription jobDescription = recipient.getPayload().getData();
+ if (jobDescription instanceof ProcessInstanceJobDescription processInstanceJobDescription && processes.isResolvable()) {
+ return processJobDescription(jobDetails, processInstanceJobDescription);
+ } else if (jobDescription instanceof UserTaskInstanceJobDescription userTaskInstanceJobDescription && userTasks.isResolvable()) {
+ return processJobDescription(jobDetails, userTaskInstanceJobDescription);
}
+
+ return Uni.createFrom().item(
+ JobExecutionResponse.builder()
+ .code("401")
+ .jobId(jobDetails.getId())
+ .now()
+ .message("job cannot be processed")
+ .build());
+ }
+
+ private Uni processJobDescription(JobDetails jobDetails, UserTaskInstanceJobDescription userTaskInstanceJobDescription) {
+ Supplier execute = () -> executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional userTaskInstance = userTasks.get().instances().findById(userTaskInstanceJobDescription.getUserTaskInstanceId());
+ if (userTaskInstance.isEmpty()) {
+ return null;
+ }
+ UserTaskInstance instance = userTaskInstance.get();
+ instance.trigger(userTaskInstanceJobDescription);
+ return null;
+ });
+
+ return Uni.createFrom().item(execute)
+ .onFailure()
+ .transform(
+ unexpected -> new JobExecutionException(jobDetails.getId(), "Unexpected error when executing Embedded request for job: " + jobDetails.getId() + ". " + unexpected.getMessage(),
+ unexpected))
+ .onItem()
+ .transform(res -> JobExecutionResponse.builder()
+ .message("Embedded job executed")
+ .code(String.valueOf(200))
+ .now()
+ .jobId(jobDetails.getId())
+ .build());
+
+ }
+
+ private Uni processJobDescription(JobDetails jobDetails, ProcessInstanceJobDescription processInstanceJobDescription) {
+ String timerId = processInstanceJobDescription.timerId();
+ String processInstanceId = processInstanceJobDescription.processInstanceId();
+ Optional> process = processes.get().processByProcessInstanceId(processInstanceId);
if (process.isEmpty()) {
return Uni.createFrom().item(
JobExecutionResponse.builder()
@@ -77,9 +122,13 @@ public Uni execute(JobDetails jobDetails) {
Integer limit = jobDetails.getRetries();
- TriggerJobCommand command = new TriggerJobCommand(processInstanceId, correlationId, timerId, limit, process.get(), application.unitOfWorkManager());
+ Supplier execute = () -> executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ TriggerJobCommand command = new TriggerJobCommand(processInstanceId, jobDetails.getCorrelationId(), timerId, limit, process.get(), application.unitOfWorkManager());
+ return command.execute();
+ });
- return Uni.createFrom().item(command::execute)
+ return Uni.createFrom()
+ .item(execute)
.onFailure()
.transform(
unexpected -> new JobExecutionException(jobDetails.getId(), "Unexpected error when executing Embedded request for job: " + jobDetails.getId() + ". " + unexpected.getMessage(),
diff --git a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobsService.java b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobsService.java
index 95b9b0d92e..84754c6dc2 100644
--- a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobsService.java
+++ b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/EmbeddedJobsService.java
@@ -20,9 +20,8 @@
import java.util.concurrent.ExecutionException;
+import org.kie.kogito.jobs.JobDescription;
import org.kie.kogito.jobs.JobsService;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
-import org.kie.kogito.jobs.ProcessJobDescription;
import org.kie.kogito.jobs.api.JobCallbackResourceDef;
import org.kie.kogito.jobs.service.adapter.JobDetailsAdapter;
import org.kie.kogito.jobs.service.api.Job;
@@ -54,13 +53,7 @@ public EmbeddedJobsService() {
}
@Override
- public String scheduleProcessJob(ProcessJobDescription description) {
- LOGGER.debug("ScheduleProcessJob: {} not supported", description);
- return null;
- }
-
- @Override
- public String scheduleProcessInstanceJob(ProcessInstanceJobDescription description) {
+ public String scheduleJob(JobDescription description) {
try {
Job job = Job.builder()
.id(description.id())
diff --git a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/InVMPayloadData.java b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/InVMPayloadData.java
index cb49a135b6..3a9cdf9286 100644
--- a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/InVMPayloadData.java
+++ b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/InVMPayloadData.java
@@ -18,31 +18,31 @@
*/
package org.kie.kogito.jobs.embedded;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.JobDescription;
import org.kie.kogito.jobs.service.api.PayloadData;
-public class InVMPayloadData extends PayloadData {
+public class InVMPayloadData extends PayloadData {
- private ProcessInstanceJobDescription jobDescription;
+ private JobDescription jobDescription;
public InVMPayloadData() {
// do nothing
}
- public void setJobDescription(ProcessInstanceJobDescription jobDescription) {
+ public void setJobDescription(JobDescription jobDescription) {
this.jobDescription = jobDescription;
}
- public ProcessInstanceJobDescription getJobDescription() {
+ public JobDescription getJobDescription() {
return jobDescription;
}
@Override
- public ProcessInstanceJobDescription getData() {
+ public JobDescription getData() {
return jobDescription;
}
- public InVMPayloadData(ProcessInstanceJobDescription data) {
+ public InVMPayloadData(JobDescription data) {
this.jobDescription = data;
}
diff --git a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/JobInVMEventPublisher.java b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/JobInVMEventPublisher.java
index dae4ac4ecf..78434dc841 100644
--- a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/JobInVMEventPublisher.java
+++ b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/main/java/org/kie/kogito/jobs/embedded/JobInVMEventPublisher.java
@@ -25,7 +25,8 @@
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.kie.kogito.event.EventPublisher;
import org.kie.kogito.event.job.JobInstanceDataEvent;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.JobDescription;
+import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
import org.kie.kogito.jobs.service.adapter.ScheduledJobAdapter;
import org.kie.kogito.jobs.service.api.Recipient;
import org.kie.kogito.jobs.service.model.JobDetails;
@@ -93,13 +94,15 @@ public void observe(@ObservesAsync EmbeddedJobServiceEvent serviceEvent) {
try {
ScheduledJob scheduledJob = ScheduledJobAdapter.of(jobDetails);
Recipient recipient = jobDetails.getRecipient().getRecipient();
- ProcessInstanceJobDescription jobDescription = recipient.getPayload().getJobDescription();
-
- scheduledJob.setProcessInstanceId(jobDescription.processInstanceId());
- scheduledJob.setProcessId(jobDescription.processId());
- scheduledJob.setRootProcessInstanceId(jobDescription.rootProcessInstanceId());
- scheduledJob.setRootProcessId(jobDescription.rootProcessId());
- scheduledJob.setNodeInstanceId(jobDescription.nodeInstanceId());
+ JobDescription jobDescription = recipient.getPayload().getJobDescription();
+
+ if (jobDescription instanceof ProcessInstanceJobDescription processInstanceJobDescription) {
+ scheduledJob.setProcessInstanceId(processInstanceJobDescription.processInstanceId());
+ scheduledJob.setProcessId(processInstanceJobDescription.processId());
+ scheduledJob.setRootProcessInstanceId(processInstanceJobDescription.rootProcessInstanceId());
+ scheduledJob.setRootProcessId(processInstanceJobDescription.rootProcessId());
+ scheduledJob.setNodeInstanceId(processInstanceJobDescription.nodeInstanceId());
+ }
byte[] jsonContent = objectMapper.writeValueAsBytes(scheduledJob);
JobInstanceDataEvent event = new JobInstanceDataEvent(JOB_EVENT_TYPE,
diff --git a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/test/java/org/kie/kogito/jobs/embedded/EmbeddedJobsServiceTest.java b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/test/java/org/kie/kogito/jobs/embedded/EmbeddedJobsServiceTest.java
index c854f86f7f..33e0c8be4b 100644
--- a/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/test/java/org/kie/kogito/jobs/embedded/EmbeddedJobsServiceTest.java
+++ b/jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs/src/test/java/org/kie/kogito/jobs/embedded/EmbeddedJobsServiceTest.java
@@ -28,7 +28,7 @@
import org.kie.kogito.event.job.JobInstanceDataEvent;
import org.kie.kogito.jobs.DurationExpirationTime;
import org.kie.kogito.jobs.JobsService;
-import org.kie.kogito.jobs.ProcessInstanceJobDescription;
+import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
import io.quarkus.test.junit.QuarkusTest;
@@ -58,7 +58,7 @@ public void testJobService() throws Exception {
CountDownLatch latch = new CountDownLatch(8);
publisher.setLatch(latch);
- ProcessInstanceJobDescription description = ProcessInstanceJobDescription.builder()
+ ProcessInstanceJobDescription description = ProcessInstanceJobDescription.newProcessInstanceJobDescriptionBuilder()
.generateId()
.timerId("-1")
.expirationTime(DurationExpirationTime.now())
@@ -68,9 +68,9 @@ public void testJobService() throws Exception {
.rootProcessId(null)
.nodeInstanceId(NODE_INSTANCE_ID)
.build();
- jobService.scheduleProcessInstanceJob(description);
+ jobService.scheduleJob(description);
- ProcessInstanceJobDescription descriptionWRootProcess = ProcessInstanceJobDescription.builder()
+ ProcessInstanceJobDescription descriptionWRootProcess = ProcessInstanceJobDescription.newProcessInstanceJobDescriptionBuilder()
.generateId()
.timerId("-1")
.expirationTime(DurationExpirationTime.now())
@@ -80,7 +80,7 @@ public void testJobService() throws Exception {
.rootProcessId(ROOT_PROCESS_ID)
.nodeInstanceId(NODE_INSTANCE_ID)
.build();
- jobService.scheduleProcessInstanceJob(descriptionWRootProcess);
+ jobService.scheduleJob(descriptionWRootProcess);
latch.await();
diff --git a/pom.xml b/pom.xml
index 554fc18758..0b560abd24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,6 @@
2024-01-16T00:00:00Z
- 3.4.1
@@ -99,9 +98,10 @@
org.apache.maven.plugins
maven-artifact-plugin
- ${version.maven.artifact.plugin}
${project.build.outputTimestamp}
+
+ image-build.zip
@@ -131,10 +131,20 @@
explainability
trusty
jitexecutor
- apps-integration-tests
+
+ allSubmodules
+
+
+ !only.reproducible
+
+
+
+ apps-integration-tests
+
+
optaplanner-downstream
diff --git a/security-commons/pom.xml b/security-commons/pom.xml
index 4e1705ec57..a26cb5abd4 100644
--- a/security-commons/pom.xml
+++ b/security-commons/pom.xml
@@ -53,11 +53,6 @@
kogito-quarkus-test-utils
test
-
- org.keycloak
- keycloak-core
- test
-
io.quarkus
quarkus-junit5
diff --git a/security-commons/src/test/java/org/kie/kogito/security/KeycloakSecurityCommonsServiceIT.java b/security-commons/src/test/java/org/kie/kogito/security/KeycloakSecurityCommonsServiceIT.java
index a013593b8c..9e238e7fed 100644
--- a/security-commons/src/test/java/org/kie/kogito/security/KeycloakSecurityCommonsServiceIT.java
+++ b/security-commons/src/test/java/org/kie/kogito/security/KeycloakSecurityCommonsServiceIT.java
@@ -19,7 +19,6 @@
package org.kie.kogito.security;
import org.junit.jupiter.api.Test;
-import org.keycloak.representations.AccessTokenResponse;
import org.kie.kogito.test.quarkus.QuarkusTestProperty;
import org.kie.kogito.testcontainers.KogitoKeycloakContainer;
import org.kie.kogito.testcontainers.quarkus.KeycloakQuarkusTestResource;
@@ -74,6 +73,6 @@ private String getAccessToken(String userName) {
.param("client_secret", KogitoKeycloakContainer.CLIENT_SECRET)
.when()
.post(keycloakURL + "/protocol/openid-connect/token")
- .as(AccessTokenResponse.class).getToken();
+ .jsonPath().get("access_token");
}
}
diff --git a/trusty/trusty-service/trusty-service-common/pom.xml b/trusty/trusty-service/trusty-service-common/pom.xml
index f58205a872..8c53ec2e92 100644
--- a/trusty/trusty-service/trusty-service-common/pom.xml
+++ b/trusty/trusty-service/trusty-service-common/pom.xml
@@ -124,11 +124,6 @@
awaitility
test
-
- org.keycloak
- keycloak-core
- test
-
org.skyscreamer
jsonassert
diff --git a/trusty/trusty-service/trusty-service-common/src/test/java/org/kie/kogito/trusty/service/common/KeycloakTrustyServiceIT.java b/trusty/trusty-service/trusty-service-common/src/test/java/org/kie/kogito/trusty/service/common/KeycloakTrustyServiceIT.java
index c860f37841..6fb21ddff6 100644
--- a/trusty/trusty-service/trusty-service-common/src/test/java/org/kie/kogito/trusty/service/common/KeycloakTrustyServiceIT.java
+++ b/trusty/trusty-service/trusty-service-common/src/test/java/org/kie/kogito/trusty/service/common/KeycloakTrustyServiceIT.java
@@ -24,7 +24,6 @@
import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
-import org.keycloak.representations.AccessTokenResponse;
import org.kie.kogito.test.quarkus.QuarkusTestProperty;
import org.kie.kogito.testcontainers.KogitoKeycloakContainer;
import org.kie.kogito.testcontainers.quarkus.KeycloakQuarkusTestResource;
@@ -77,6 +76,6 @@ private String getAccessToken(String userName) {
.param("client_secret", KogitoKeycloakContainer.CLIENT_SECRET)
.when()
.post(keycloakURL + "/protocol/openid-connect/token")
- .as(AccessTokenResponse.class).getToken();
+ .jsonPath().get("access_token");
}
}