diff --git a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/MongoDBEventPublisher.java b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/MongoDBEventPublisher.java index 3f1ace06a8b..5ee97577427 100644 --- a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/MongoDBEventPublisher.java +++ b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/MongoDBEventPublisher.java @@ -19,7 +19,6 @@ package org.kie.kogito.events.mongodb; import java.util.Collection; -import java.util.function.BooleanSupplier; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; @@ -27,8 +26,7 @@ import org.kie.kogito.event.DataEvent; import org.kie.kogito.event.EventPublisher; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; import org.kie.kogito.events.mongodb.codec.EventMongoDBCodecProvider; import org.kie.kogito.mongodb.transaction.AbstractTransactionManager; import org.slf4j.Logger; @@ -50,7 +48,6 @@ public abstract class MongoDBEventPublisher implements EventPublisher { private MongoCollection processInstanceDataEventCollection; private MongoCollection userTaskInstanceDataEventCollection; - private MongoCollection variableInstanceDataEventCollection; protected abstract MongoClient mongoClient(); @@ -60,54 +57,47 @@ public abstract class MongoDBEventPublisher implements EventPublisher { protected abstract boolean userTasksEvents(); - protected abstract boolean variablesEvents(); - protected abstract String eventsDatabaseName(); protected abstract String processInstancesEventsCollection(); protected abstract String userTasksEventsCollection(); - protected abstract String variablesEventsCollection(); - protected void configure() { CodecRegistry registry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), fromProviders(new EventMongoDBCodecProvider(), PojoCodecProvider.builder().automatic(true).build())); MongoDatabase mongoDatabase = mongoClient().getDatabase(eventsDatabaseName()).withCodecRegistry(registry); processInstanceDataEventCollection = mongoDatabase.getCollection(processInstancesEventsCollection(), ProcessInstanceDataEvent.class).withCodecRegistry(registry); userTaskInstanceDataEventCollection = mongoDatabase.getCollection(userTasksEventsCollection(), UserTaskInstanceDataEvent.class).withCodecRegistry(registry); - variableInstanceDataEventCollection = mongoDatabase.getCollection(variablesEventsCollection(), VariableInstanceDataEvent.class).withCodecRegistry(registry); } @Override public void publish(DataEvent event) { - switch (event.getType()) { - case "ProcessInstanceEvent": - publishEvent(processInstanceDataEventCollection, (ProcessInstanceDataEvent) event, this::processInstancesEvents); - break; - case "UserTaskInstanceEvent": - publishEvent(userTaskInstanceDataEventCollection, (UserTaskInstanceDataEvent) event, this::userTasksEvents); - break; - case "VariableInstanceEvent": - publishEvent(variableInstanceDataEventCollection, (VariableInstanceDataEvent) event, this::variablesEvents); - break; - default: - logger.warn("Unknown type of event '{}', ignoring", event.getType()); + if (this.processInstancesEvents() && event instanceof ProcessInstanceDataEvent) { + publishEvent(processInstanceDataEventCollection, (ProcessInstanceDataEvent) event); + return; + } + + if (this.userTasksEvents() && event instanceof UserTaskInstanceDataEvent) { + publishEvent(userTaskInstanceDataEventCollection, (UserTaskInstanceDataEvent) event); + return; } + + logger.debug("Unknown type of event '{}', ignoring", event.getType()); + } - private > void publishEvent(MongoCollection collection, T event, BooleanSupplier enabled) { - if (enabled.getAsBoolean()) { - if (transactionManager().enabled()) { - collection.insertOne(transactionManager().getClientSession(), event); - // delete the event immediately from the outbox collection - collection.deleteOne(transactionManager().getClientSession(), Filters.eq(ID, event.getId())); - } else { - collection.insertOne(event); - // delete the event from the outbox collection - collection.deleteOne(Filters.eq(ID, event.getId())); - } + private > void publishEvent(MongoCollection collection, T event) { + if (transactionManager().enabled()) { + collection.insertOne(transactionManager().getClientSession(), event); + // delete the event immediately from the outbox collection + collection.deleteOne(transactionManager().getClientSession(), Filters.eq(ID, event.getId())); + } else { + collection.insertOne(event); + // delete the event from the outbox collection + collection.deleteOne(Filters.eq(ID, event.getId())); } + } @Override diff --git a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProvider.java b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProvider.java index 8dc513fcbd2..3b13948cf7d 100644 --- a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProvider.java +++ b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProvider.java @@ -22,27 +22,22 @@ import org.bson.codecs.configuration.CodecProvider; import org.bson.codecs.configuration.CodecRegistry; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; public class EventMongoDBCodecProvider implements CodecProvider { private static final ProcessInstanceDataEventCodec PROCESS_INSTANCE_DATA_EVENT_CODEC = new ProcessInstanceDataEventCodec(); private static final UserTaskInstanceDataEventCodec USER_TASK_INSTANCE_DATA_EVENT_CODEC = new UserTaskInstanceDataEventCodec(); - private static final VariableInstanceDataEventCodec VARIABLE_INSTANCE_DATA_EVENT_CODEC = new VariableInstanceDataEventCodec(); @SuppressWarnings("unchecked") @Override public Codec get(Class aClass, CodecRegistry codecRegistry) { - if (aClass == ProcessInstanceDataEvent.class) { + if (ProcessInstanceDataEvent.class.isAssignableFrom(aClass)) { return (Codec) PROCESS_INSTANCE_DATA_EVENT_CODEC; } - if (aClass == UserTaskInstanceDataEvent.class) { + if (UserTaskInstanceDataEvent.class.isAssignableFrom(aClass)) { return (Codec) USER_TASK_INSTANCE_DATA_EVENT_CODEC; } - if (aClass == VariableInstanceDataEvent.class) { - return (Codec) VARIABLE_INSTANCE_DATA_EVENT_CODEC; - } return null; } } diff --git a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodec.java b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodec.java index aff39fd05f8..8fbf46a1b88 100644 --- a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodec.java +++ b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodec.java @@ -18,8 +18,6 @@ */ package org.kie.kogito.events.mongodb.codec; -import java.util.stream.Collectors; - import org.bson.BsonReader; import org.bson.BsonString; import org.bson.BsonValue; @@ -29,13 +27,19 @@ import org.bson.codecs.DecoderContext; import org.bson.codecs.EncoderContext; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import static org.kie.kogito.events.mongodb.codec.CodecUtils.codec; -import static org.kie.kogito.events.mongodb.codec.CodecUtils.encodeDataEvent; public class ProcessInstanceDataEventCodec implements CollectibleCodec { + private static final Logger LOGGER = LoggerFactory.getLogger(ProcessInstanceDataEventCodec.class); + @Override public ProcessInstanceDataEvent generateIdIfAbsentFromDocument(ProcessInstanceDataEvent processInstanceDataEvent) { return processInstanceDataEvent; @@ -61,76 +65,16 @@ public ProcessInstanceDataEvent decode(BsonReader bsonReader, DecoderContext dec @Override public void encode(BsonWriter bsonWriter, ProcessInstanceDataEvent processInstanceDataEvent, EncoderContext encoderContext) { - Document doc = new Document(); - encodeDataEvent(doc, processInstanceDataEvent); - doc.put("kogitoProcessType", processInstanceDataEvent.getKogitoProcessType()); - doc.put("kogitoProcessInstanceVersion", processInstanceDataEvent.getKogitoProcessInstanceVersion()); - doc.put("kogitoParentProcessinstanceId", processInstanceDataEvent.getKogitoParentProcessInstanceId()); - doc.put("kogitoProcessinstanceState", processInstanceDataEvent.getKogitoProcessInstanceState()); - doc.put("kogitoReferenceId", processInstanceDataEvent.getKogitoReferenceId()); - doc.put("kogitoStartFromNode", processInstanceDataEvent.getKogitoStartFromNode()); - doc.put("kogitoIdentity", processInstanceDataEvent.getKogitoIdentity()); - doc.put("data", encodeData(processInstanceDataEvent.getData())); - codec().encode(bsonWriter, doc, encoderContext); - } - - private Document encodeData(ProcessInstanceEventBody data) { - Document doc = new Document(); - doc.put("id", data.getId()); - doc.put("version", data.getVersion()); - doc.put("parentInstanceId", data.getParentInstanceId()); - doc.put("rootInstanceId", data.getRootInstanceId()); - doc.put("processId", data.getProcessId()); - doc.put("processType", data.getProcessType()); - doc.put("rootProcessId", data.getRootProcessId()); - doc.put("processName", data.getProcessName()); - doc.put("startDate", data.getStartDate()); - doc.put("endDate", data.getEndDate()); - doc.put("state", data.getState()); - doc.put("businessKey", data.getBusinessKey()); - doc.put("roles", data.getRoles()); - doc.put("identity", data.getIdentity()); - - if (data.getVariables() != null) { - doc.put("variables", new Document(data.getVariables())); + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.findAndRegisterModules(); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + Document document = Document.parse(mapper.writeValueAsString(processInstanceDataEvent)); + document.put(CodecUtils.ID, processInstanceDataEvent.getId()); + codec().encode(bsonWriter, document, encoderContext); + } catch (JsonProcessingException e) { + LOGGER.error("Could not process json event", e); } - - if (data.getNodeInstances() != null) { - doc.put("nodeInstances", - data.getNodeInstances().stream().map(ni -> { - Document niDoc = new Document(); - niDoc.put("id", ni.getId()); - niDoc.put("nodeId", ni.getNodeId()); - niDoc.put("nodeDefinitionId", ni.getNodeDefinitionId()); - niDoc.put("nodeName", ni.getNodeName()); - niDoc.put("nodeType", ni.getNodeType()); - niDoc.put("triggerTime", ni.getTriggerTime()); - if (ni.getLeaveTime() != null) { - niDoc.put("leaveTime", ni.getLeaveTime()); - } - return niDoc; - }).collect(Collectors.toSet())); - } - - if (data.getError() != null) { - Document eDoc = new Document(); - eDoc.put("errorMessage", data.getError().getErrorMessage()); - eDoc.put("nodeDefinitionId", data.getError().getNodeDefinitionId()); - doc.put("error", eDoc); - } - - if (data.getMilestones() != null) { - doc.put("milestones", - data.getMilestones().stream().map(m -> { - Document mDoc = new Document(); - mDoc.put("id", m.getId()); - mDoc.put("name", m.getName()); - mDoc.put("status", m.getStatus()); - return mDoc; - }).collect(Collectors.toSet())); - } - - return doc; } @Override diff --git a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodec.java b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodec.java index d0245876567..24087cf4397 100644 --- a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodec.java +++ b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodec.java @@ -18,8 +18,6 @@ */ package org.kie.kogito.events.mongodb.codec; -import java.util.stream.Collectors; - import org.bson.BsonReader; import org.bson.BsonString; import org.bson.BsonValue; @@ -28,16 +26,22 @@ import org.bson.codecs.CollectibleCodec; import org.bson.codecs.DecoderContext; import org.bson.codecs.EncoderContext; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import static org.kie.kogito.events.mongodb.codec.CodecUtils.codec; -import static org.kie.kogito.events.mongodb.codec.CodecUtils.encodeDataEvent; public class UserTaskInstanceDataEventCodec implements CollectibleCodec { + private static final Logger LOGGER = LoggerFactory.getLogger(UserTaskInstanceDataEventCodec.class); + @Override - public UserTaskInstanceDataEvent generateIdIfAbsentFromDocument(UserTaskInstanceDataEvent userTaskInstanceDataEvent) { + public UserTaskInstanceDataEvent generateIdIfAbsentFromDocument(UserTaskInstanceDataEvent userTaskInstanceDataEvent) { return userTaskInstanceDataEvent; } @@ -61,64 +65,16 @@ public UserTaskInstanceDataEvent decode(BsonReader bsonReader, DecoderContext de @Override public void encode(BsonWriter bsonWriter, UserTaskInstanceDataEvent userTaskInstanceDataEvent, EncoderContext encoderContext) { - Document doc = new Document(); - encodeDataEvent(doc, userTaskInstanceDataEvent); - doc.put("kogitoUserTaskinstanceId", userTaskInstanceDataEvent.getKogitoUserTaskinstanceId()); - doc.put("kogitoUserTaskinstanceState", userTaskInstanceDataEvent.getKogitoUserTaskinstanceState()); - doc.put("data", encodeData(userTaskInstanceDataEvent.getData())); - codec().encode(bsonWriter, doc, encoderContext); - } - - private Document encodeData(UserTaskInstanceEventBody data) { - Document doc = new Document(); - doc.put("id", data.getId()); - doc.put("taskName", data.getTaskName()); - doc.put("taskDescription", data.getTaskDescription()); - doc.put("taskPriority", data.getTaskPriority()); - doc.put("referenceName", data.getReferenceName()); - doc.put("startDate", data.getStartDate()); - doc.put("completeDate", data.getCompleteDate()); - doc.put("state", data.getState()); - doc.put("actualOwner", data.getActualOwner()); - doc.put("potentialUsers", data.getPotentialUsers()); - doc.put("potentialGroups", data.getPotentialGroups()); - doc.put("excludedUsers", data.getExcludedUsers()); - doc.put("adminUsers", data.getAdminUsers()); - doc.put("adminGroups", data.getAdminGroups()); - doc.put("inputs", new Document(data.getInputs())); - doc.put("outputs", new Document(data.getOutputs())); - doc.put("processInstanceId", data.getProcessInstanceId()); - doc.put("rootProcessInstanceId", data.getRootProcessInstanceId()); - doc.put("processId", data.getProcessId()); - doc.put("rootProcessId", data.getRootProcessId()); - doc.put("identity", data.getIdentity()); - - if (data.getComments() != null) { - doc.put("comments", - data.getComments().stream().map(c -> { - Document cDoc = new Document(); - cDoc.put("id", c.getId()); - cDoc.put("content", c.getContent()); - cDoc.put("updatedAt", c.getUpdatedAt()); - cDoc.put("updatedBy", c.getUpdatedBy()); - return cDoc; - }).collect(Collectors.toSet())); - } - - if (data.getAttachments() != null) { - doc.put("attachments", - data.getAttachments().stream().map(a -> { - Document aDoc = new Document(); - aDoc.put("id", a.getId()); - aDoc.put("content", a.getContent()); - aDoc.put("updatedAt", a.getUpdatedAt()); - aDoc.put("updatedBy", a.getUpdatedBy()); - aDoc.put("name", a.getName()); - return aDoc; - }).collect(Collectors.toSet())); + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.findAndRegisterModules(); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + Document document = Document.parse(mapper.writeValueAsString(userTaskInstanceDataEvent)); + document.put(CodecUtils.ID, userTaskInstanceDataEvent.getId()); + codec().encode(bsonWriter, document, encoderContext); + } catch (JsonProcessingException e) { + LOGGER.error("Could not process json event", e); } - - return doc; } @Override diff --git a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/VariableInstanceDataEventCodec.java b/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/VariableInstanceDataEventCodec.java deleted file mode 100644 index e5a6fb8f9bd..00000000000 --- a/addons/common/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/codec/VariableInstanceDataEventCodec.java +++ /dev/null @@ -1,90 +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.events.mongodb.codec; - -import org.bson.BsonReader; -import org.bson.BsonString; -import org.bson.BsonValue; -import org.bson.BsonWriter; -import org.bson.Document; -import org.bson.codecs.CollectibleCodec; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.EncoderContext; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; - -import static org.kie.kogito.events.mongodb.codec.CodecUtils.codec; -import static org.kie.kogito.events.mongodb.codec.CodecUtils.encodeDataEvent; - -public class VariableInstanceDataEventCodec implements CollectibleCodec { - - @Override - public VariableInstanceDataEvent generateIdIfAbsentFromDocument(VariableInstanceDataEvent variableInstanceDataEvent) { - return variableInstanceDataEvent; - } - - @Override - public boolean documentHasId(VariableInstanceDataEvent variableInstanceDataEvent) { - return variableInstanceDataEvent.getId() != null; - } - - @Override - public BsonValue getDocumentId(VariableInstanceDataEvent variableInstanceDataEvent) { - return new BsonString(variableInstanceDataEvent.getId()); - } - - @Override - public VariableInstanceDataEvent decode(BsonReader bsonReader, DecoderContext decoderContext) { - // The events persist in an outbox collection - // The events are deleted immediately (in the same transaction) - // "decode" is not supposed to take place in any scenario - return null; - } - - @Override - public void encode(BsonWriter bsonWriter, VariableInstanceDataEvent variableInstanceDataEvent, EncoderContext encoderContext) { - Document doc = new Document(); - encodeDataEvent(doc, variableInstanceDataEvent); - doc.put("kogitoVariableName", variableInstanceDataEvent.getKogitoVariableName()); - doc.put("data", encodeData(variableInstanceDataEvent.getData())); - codec().encode(bsonWriter, doc, encoderContext); - } - - private Document encodeData(VariableInstanceEventBody data) { - Document doc = new Document(); - doc.put("variableName", data.getVariableName()); - doc.put("variableValue", data.getVariableValue()); - doc.put("variablePreviousValue", data.getVariablePreviousValue()); - doc.put("changeDate", data.getChangeDate()); - doc.put("changedByNodeId", data.getChangedByNodeId()); - doc.put("changedByNodeName", data.getChangedByNodeName()); - doc.put("changedByNodeType", data.getChangedByNodeType()); - doc.put("identity", data.getIdentity()); - doc.put("processInstanceId", data.getProcessInstanceId()); - doc.put("rootProcessInstanceId", data.getRootProcessInstanceId()); - doc.put("processId", data.getProcessId()); - doc.put("rootProcessId", data.getRootProcessId()); - return doc; - } - - @Override - public Class getEncoderClass() { - return VariableInstanceDataEvent.class; - } -} diff --git a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/MongoDBEventPublisherTest.java b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/MongoDBEventPublisherTest.java index b62db62b153..f83b5ea44c6 100644 --- a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/MongoDBEventPublisherTest.java +++ b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/MongoDBEventPublisherTest.java @@ -27,8 +27,9 @@ import org.kie.kogito.event.AbstractDataEvent; import org.kie.kogito.event.DataEvent; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent; import org.kie.kogito.mongodb.transaction.AbstractTransactionManager; import com.mongodb.client.ClientSession; @@ -39,7 +40,7 @@ import static org.kie.kogito.events.mongodb.MongoDBEventPublisher.ID; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.eq; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -55,11 +56,9 @@ class MongoDBEventPublisherTest { private MongoCollection mongoCollection; - private ProcessInstanceDataEvent processInstanceDataEvent; + private ProcessInstanceStateDataEvent processInstanceDataEvent; - private UserTaskInstanceDataEvent userTaskInstanceDataEvent; - - private VariableInstanceDataEvent variableInstanceDataEvent; + private UserTaskInstanceStateDataEvent userTaskInstanceDataEvent; private AbstractDataEvent event; @@ -84,11 +83,6 @@ protected boolean userTasksEvents() { return true; } - @Override - protected boolean variablesEvents() { - return true; - } - @Override protected String eventsDatabaseName() { return "testDB"; @@ -104,10 +98,6 @@ protected String userTasksEventsCollection() { return "testTECollection"; } - @Override - protected String variablesEventsCollection() { - return "testVCollection"; - } }; @BeforeEach @@ -122,18 +112,14 @@ void setUp() { transactionManager = mock(AbstractTransactionManager.class); - processInstanceDataEvent = mock(ProcessInstanceDataEvent.class); + processInstanceDataEvent = mock(ProcessInstanceStateDataEvent.class); when(processInstanceDataEvent.getType()).thenReturn("ProcessInstanceEvent"); when(processInstanceDataEvent.getId()).thenReturn("testProcessInstanceEvent"); - userTaskInstanceDataEvent = mock(UserTaskInstanceDataEvent.class); + userTaskInstanceDataEvent = mock(UserTaskInstanceStateDataEvent.class); when(userTaskInstanceDataEvent.getType()).thenReturn("UserTaskInstanceEvent"); when(userTaskInstanceDataEvent.getId()).thenReturn("testUserTaskInstanceEvent"); - variableInstanceDataEvent = mock(VariableInstanceDataEvent.class); - when(variableInstanceDataEvent.getType()).thenReturn("VariableInstanceEvent"); - when(variableInstanceDataEvent.getId()).thenReturn("testVariableInstanceEvent"); - event = mock(AbstractDataEvent.class); when(event.getType()).thenReturn("test"); } @@ -144,9 +130,8 @@ void configure() { verify(mongoClient).getDatabase(eq("testDB")); verify(mongoDatabase).getCollection(eq("testPICollection"), eq(ProcessInstanceDataEvent.class)); verify(mongoDatabase).getCollection(eq("testTECollection"), eq(UserTaskInstanceDataEvent.class)); - verify(mongoDatabase).getCollection(eq("testVCollection"), eq(VariableInstanceDataEvent.class)); verify(mongoDatabase).withCodecRegistry(any(CodecRegistry.class)); - verify(mongoCollection, times(3)).withCodecRegistry(any(CodecRegistry.class)); + verify(mongoCollection, times(2)).withCodecRegistry(any(CodecRegistry.class)); } @Test @@ -161,13 +146,9 @@ void publish() { verify(mongoCollection).insertOne(eq(userTaskInstanceDataEvent)); verify(mongoCollection).deleteOne(eq(Filters.eq(ID, "testUserTaskInstanceEvent"))); - publisher.publish(variableInstanceDataEvent); - verify(mongoCollection).insertOne(eq(variableInstanceDataEvent)); - verify(mongoCollection).deleteOne(eq(Filters.eq(ID, "testVariableInstanceEvent"))); - publisher.publish(event); - verify(mongoCollection, times(3)).insertOne(any()); - verify(mongoCollection, times(3)).deleteOne(any()); + verify(mongoCollection, times(2)).insertOne(any()); + verify(mongoCollection, times(2)).deleteOne(any()); } @Test @@ -186,13 +167,9 @@ void publish_withTransaction() { verify(mongoCollection).insertOne(eq(clientSession), eq(userTaskInstanceDataEvent)); verify(mongoCollection).deleteOne(eq(clientSession), eq(Filters.eq(ID, "testUserTaskInstanceEvent"))); - publisher.publish(variableInstanceDataEvent); - verify(mongoCollection).insertOne(eq(clientSession), eq(variableInstanceDataEvent)); - verify(mongoCollection).deleteOne(eq(clientSession), eq(Filters.eq(ID, "testVariableInstanceEvent"))); - publisher.publish(event); - verify(mongoCollection, times(3)).insertOne(eq(clientSession), any(AbstractDataEvent.class)); - verify(mongoCollection, times(3)).deleteOne(eq(clientSession), any()); + verify(mongoCollection, times(2)).insertOne(eq(clientSession), any(AbstractDataEvent.class)); + verify(mongoCollection, times(2)).deleteOne(eq(clientSession), any()); } @Test @@ -202,13 +179,12 @@ void testPublishEvents() { List> events = new ArrayList<>(); events.add(processInstanceDataEvent); events.add(userTaskInstanceDataEvent); - events.add(variableInstanceDataEvent); events.add(event); publisher.publish(events); - verify(mongoCollection, times(3)).insertOne(any()); - verify(mongoCollection, times(3)).deleteOne(any()); + verify(mongoCollection, times(2)).insertOne(any()); + verify(mongoCollection, times(2)).deleteOne(any()); verify(mongoCollection).insertOne(eq(processInstanceDataEvent)); verify(mongoCollection).deleteOne(eq(Filters.eq(ID, "testProcessInstanceEvent"))); @@ -216,8 +192,6 @@ void testPublishEvents() { verify(mongoCollection).insertOne(eq(userTaskInstanceDataEvent)); verify(mongoCollection).deleteOne(eq(Filters.eq(ID, "testUserTaskInstanceEvent"))); - verify(mongoCollection).insertOne(eq(variableInstanceDataEvent)); - verify(mongoCollection).deleteOne(eq(Filters.eq(ID, "testVariableInstanceEvent"))); } @Test @@ -231,13 +205,12 @@ void testPublishEvents_withTransaction() { List> events = new ArrayList<>(); events.add(processInstanceDataEvent); events.add(userTaskInstanceDataEvent); - events.add(variableInstanceDataEvent); events.add(event); publisher.publish(events); - verify(mongoCollection, times(3)).insertOne(eq(clientSession), any(AbstractDataEvent.class)); - verify(mongoCollection, times(3)).deleteOne(eq(clientSession), any()); + verify(mongoCollection, times(2)).insertOne(eq(clientSession), any(AbstractDataEvent.class)); + verify(mongoCollection, times(2)).deleteOne(eq(clientSession), any()); verify(mongoCollection).insertOne(eq(clientSession), eq(processInstanceDataEvent)); verify(mongoCollection).deleteOne(eq(clientSession), eq(Filters.eq(ID, "testProcessInstanceEvent"))); @@ -245,7 +218,5 @@ void testPublishEvents_withTransaction() { verify(mongoCollection).insertOne(eq(clientSession), eq(userTaskInstanceDataEvent)); verify(mongoCollection).deleteOne(eq(clientSession), eq(Filters.eq(ID, "testUserTaskInstanceEvent"))); - verify(mongoCollection).insertOne(eq(clientSession), eq(variableInstanceDataEvent)); - verify(mongoCollection).deleteOne(eq(clientSession), eq(Filters.eq(ID, "testVariableInstanceEvent"))); } } diff --git a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/CodecUtilsTest.java b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/CodecUtilsTest.java index 9392600a16d..13e5bce7970 100644 --- a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/CodecUtilsTest.java +++ b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/CodecUtilsTest.java @@ -24,9 +24,9 @@ import org.bson.Document; import org.bson.codecs.DocumentCodec; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; +import org.kie.kogito.event.process.ProcessInstanceVariableEventBody; import static org.assertj.core.api.Assertions.assertThat; import static org.kie.kogito.events.mongodb.codec.CodecUtils.ID; @@ -45,14 +45,14 @@ void encodeDataEvent() { String kogitoAddons = "testKogitoAddons"; String identity = "testKogitoIdentity"; - Map metaData = new HashMap<>(); - metaData.put(ProcessInstanceEventBody.ID_META_DATA, kogitoProcessInstanceId); - metaData.put(ProcessInstanceEventBody.VERSION_META_DATA, kogitoProcessInstanceVersion); - metaData.put(ProcessInstanceEventBody.ROOT_ID_META_DATA, kogitoRootProcessInstanceId); - metaData.put(ProcessInstanceEventBody.PROCESS_ID_META_DATA, kogitoProcessId); - metaData.put(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA, kogitoRootProcessId); + Map metaData = new HashMap<>(); + metaData.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, kogitoProcessInstanceId); + metaData.put(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA, kogitoProcessInstanceVersion); + metaData.put(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA, kogitoRootProcessInstanceId); + metaData.put(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA, kogitoProcessId); + metaData.put(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA, kogitoRootProcessId); - VariableInstanceDataEvent event = new VariableInstanceDataEvent(source, kogitoAddons, identity, metaData, mock(VariableInstanceEventBody.class)); + ProcessInstanceVariableDataEvent event = new ProcessInstanceVariableDataEvent(source, kogitoAddons, identity, metaData, mock(ProcessInstanceVariableEventBody.class)); Document doc = new Document(); CodecUtils.encodeDataEvent(doc, event); diff --git a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProviderTest.java b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProviderTest.java index ef512179d0c..55229a1a8a8 100644 --- a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProviderTest.java +++ b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/EventMongoDBCodecProviderTest.java @@ -20,8 +20,7 @@ import org.junit.jupiter.api.Test; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; import static org.assertj.core.api.Assertions.assertThat; @@ -33,7 +32,6 @@ void get() { assertThat(provider.get(ProcessInstanceDataEvent.class, null).getClass()).isEqualTo(ProcessInstanceDataEventCodec.class); assertThat(provider.get(UserTaskInstanceDataEvent.class, null).getClass()).isEqualTo(UserTaskInstanceDataEventCodec.class); - assertThat(provider.get(VariableInstanceDataEvent.class, null).getClass()).isEqualTo(VariableInstanceDataEventCodec.class); assertThat(provider.get(String.class, null)).isNull(); } } \ No newline at end of file diff --git a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodecTest.java b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodecTest.java index 05c3ce6a4c2..a7f3371526c 100644 --- a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodecTest.java +++ b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/ProcessInstanceDataEventCodecTest.java @@ -18,12 +18,9 @@ */ package org.kie.kogito.events.mongodb.codec; -import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.bson.BsonReader; import org.bson.BsonString; @@ -34,14 +31,16 @@ import org.bson.codecs.EncoderContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.MilestoneEventBody; -import org.kie.kogito.event.process.NodeInstanceEventBody; -import org.kie.kogito.event.process.ProcessErrorEventBody; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateEventBody; import org.mockito.ArgumentCaptor; import org.mockito.MockedStatic; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import static org.assertj.core.api.Assertions.assertThat; import static org.kie.kogito.events.mongodb.codec.CodecUtils.ID; import static org.mockito.ArgumentMatchers.any; @@ -55,7 +54,7 @@ class ProcessInstanceDataEventCodecTest { private ProcessInstanceDataEventCodec codec; - private ProcessInstanceDataEvent event; + private ProcessInstanceStateDataEvent event; @BeforeEach void setUp() { @@ -65,54 +64,33 @@ void setUp() { String kogitoAddons = "testKogitoAddons"; String identity = "testIdentity"; - Map metaData = new HashMap<>(); - metaData.put(ProcessInstanceEventBody.ID_META_DATA, "testKogitoProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.VERSION_META_DATA, "testKogitoProcessInstanceVersion"); - metaData.put(ProcessInstanceEventBody.ROOT_ID_META_DATA, "testKogitoRootProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.PROCESS_ID_META_DATA, "testKogitoProcessId"); - metaData.put(ProcessInstanceEventBody.PROCESS_TYPE_META_DATA, "testKogitoProcessType"); - metaData.put(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA, "testKogitoRootProcessId"); - metaData.put(ProcessInstanceEventBody.PARENT_ID_META_DATA, "testKogitoParentProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.STATE_META_DATA, "testKogitoProcessInstanceState"); - - ProcessInstanceEventBody body = ProcessInstanceEventBody.create() - .id("testId") - .version("testVersion") + Map metaData = new HashMap<>(); + metaData.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, "testKogitoProcessInstanceId"); + metaData.put(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA, "testKogitoProcessInstanceVersion"); + metaData.put(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA, "testKogitoRootProcessInstanceId"); + metaData.put(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA, "testKogitoProcessId"); + metaData.put(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA, "testKogitoProcessType"); + metaData.put(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA, "testKogitoRootProcessId"); + metaData.put(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA, "testKogitoParentProcessInstanceId"); + metaData.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA, "testKogitoProcessInstanceState"); + + ProcessInstanceStateEventBody body = ProcessInstanceStateEventBody.create() + .processInstanceId("testId") + .processVersion("testVersion") .parentInstanceId("testKogitoParentProcessInstanceId") - .rootInstanceId("testKogitoRootProcessInstanceId") + .rootProcessInstanceId("testKogitoRootProcessInstanceId") .processId("testKogitoProcessId") .processType("testKogitoProcessType") .rootProcessId("testKogitoRootProcessId") .processName("testProcessName") - .identity(identity) - .startDate(new Date()) - .endDate(new Date()) + .eventUser(identity) + .eventDate(new Date()) .state(1) .businessKey("testBusinessKey") - .error(ProcessErrorEventBody.create() - .errorMessage("testErrorMessage") - .nodeDefinitionId("testNodeDefinitionId") - .build()) - .nodeInstance(NodeInstanceEventBody.create() - .id("testId") - .nodeId("testNodeId") - .nodeDefinitionId("testNodeDefinitionId") - .nodeName("testNodeName") - .nodeType("testNodeType") - .triggerTime(new Date()) - .leaveTime(new Date()) - .build()) - .variables(Collections.singletonMap("testVariableKey", "testVariableValue")) .roles("testRole") - .milestones(Collections.singleton( - MilestoneEventBody.create() - .id("testId") - .name("testName") - .status("testStatus") - .build())) .build(); - event = new ProcessInstanceDataEvent(source, kogitoAddons, identity, metaData, body); + event = new ProcessInstanceStateDataEvent(source, kogitoAddons, identity, metaData, body); } @Test @@ -149,58 +127,36 @@ void encode() { ArgumentCaptor captor = ArgumentCaptor.forClass(Document.class); verify(mockCodec, times(1)).encode(eq(writer), captor.capture(), eq(context)); Document doc = captor.getValue(); + Map node = new ObjectMapper().readValue(doc.toJson(), Map.class); - assertThat(doc).containsEntry(ID, event.getId()) + assertThat(node).containsEntry(ID, event.getId()) .containsEntry("specversion", event.getSpecVersion().toString()) .containsEntry("source", event.getSource().toString()) .containsEntry("type", event.getType()) - .containsEntry("time", event.getTime()) - .containsEntry("subject", event.getSubject()) - .containsEntry("dataContentType", event.getDataContentType()) - .containsEntry("dataSchema", event.getDataSchema()) - .containsEntry("kogitoProcessinstanceId", event.getKogitoProcessInstanceId()) - .containsEntry("kogitoProcessInstanceVersion", event.getKogitoProcessInstanceVersion()) - .containsEntry("kogitoRootProcessinstanceId", event.getKogitoRootProcessInstanceId()) - .containsEntry("kogitoProcessId", event.getKogitoProcessId()) - .containsEntry("kogitoProcessType", event.getKogitoProcessType()) - .containsEntry("kogitoRootProcessId", event.getKogitoRootProcessId()) - .containsEntry("kogitoAddons", event.getKogitoAddons()) - .containsEntry("kogitoParentProcessinstanceId", event.getKogitoParentProcessInstanceId()) - .containsEntry("kogitoProcessinstanceState", event.getKogitoProcessInstanceState()) - .containsEntry("kogitoReferenceId", event.getKogitoReferenceId()) - .containsEntry("kogitoIdentity", event.getKogitoIdentity()) - .containsEntry("kogitoStartFromNode", event.getKogitoStartFromNode()); - - assertThat(((Document) doc.get("data"))).containsEntry("id", event.getData().getId()) - .containsEntry("version", event.getData().getVersion()) - .containsEntry("parentInstanceId", event.getData().getParentInstanceId()) - .containsEntry("rootInstanceId", event.getData().getRootInstanceId()) + .containsEntry("datacontenttype", event.getDataContentType()) + .containsEntry("kogitoprocinstanceid", event.getKogitoProcessInstanceId()) + .containsEntry("kogitoprocversion", event.getKogitoProcessInstanceVersion()) + .containsEntry("kogitorootprociid", event.getKogitoRootProcessInstanceId()) + .containsEntry("kogitoprocid", event.getKogitoProcessId()) + .containsEntry("kogitoproctype", event.getKogitoProcessType()) + .containsEntry("kogitorootprocid", event.getKogitoRootProcessId()) + .containsEntry("kogitoaddons", event.getKogitoAddons()) + .containsEntry("kogitoparentprociid", event.getKogitoParentProcessInstanceId()) + .containsEntry("kogitoprocist", event.getKogitoProcessInstanceState()) + .containsEntry("kogitoidentity", event.getKogitoIdentity()); + + assertThat(((Document) doc.get("data"))) + .containsEntry("processVersion", event.getData().getProcessVersion()) + .containsEntry("rootProcessInstanceId", event.getData().getRootProcessInstanceId()) .containsEntry("processId", event.getData().getProcessId()) .containsEntry("rootProcessId", event.getData().getRootProcessId()) .containsEntry("processName", event.getData().getProcessName()) - .containsEntry("identity", event.getData().getIdentity()) - .containsEntry("startDate", event.getData().getStartDate()) - .containsEntry("endDate", event.getData().getEndDate()) + .containsEntry("eventUser", event.getData().getEventUser()) .containsEntry("state", event.getData().getState()) - .containsEntry("businessKey", event.getData().getBusinessKey()) - .containsEntry("roles", event.getData().getRoles()) - .containsEntry("variables", new Document(event.getData().getVariables())); - Document error = new Document().append("errorMessage", event.getData().getError().getErrorMessage()) - .append("nodeDefinitionId", event.getData().getError().getNodeDefinitionId()); - assertThat(((Document) doc.get("data"))).containsEntry("error", error); - NodeInstanceEventBody ni = event.getData().getNodeInstances().iterator().next(); - Document nodeInstance = new Document().append("id", ni.getId()).append("nodeId", ni.getNodeId()) - .append("nodeDefinitionId", ni.getNodeDefinitionId()).append("nodeName", ni.getNodeName()) - .append("nodeType", ni.getNodeType()).append("triggerTime", ni.getTriggerTime()) - .append("leaveTime", ni.getLeaveTime()); - Set nodeInstances = new HashSet<>(); - nodeInstances.add(nodeInstance); - assertThat(((Document) doc.get("data"))).containsEntry("nodeInstances", nodeInstances); - MilestoneEventBody mi = event.getData().getMilestones().iterator().next(); - Document milestone = new Document().append("id", mi.getId()).append("name", mi.getName()).append("status", mi.getStatus()); - Set milestones = new HashSet<>(); - milestones.add(milestone); - assertThat(((Document) doc.get("data"))).containsEntry("milestones", milestones); + .containsEntry("businessKey", event.getData().getBusinessKey()); + + } catch (JsonProcessingException e) { + e.printStackTrace(); } } diff --git a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodecTest.java b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodecTest.java index 6b4253c242f..7aeada7f966 100644 --- a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodecTest.java +++ b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/UserTaskInstanceDataEventCodecTest.java @@ -18,13 +18,9 @@ */ package org.kie.kogito.events.mongodb.codec; -import java.net.URI; -import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.bson.BsonReader; import org.bson.BsonString; @@ -35,14 +31,17 @@ import org.bson.codecs.EncoderContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.AttachmentEventBody; -import org.kie.kogito.event.process.CommentEventBody; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceEventMetadata; +import org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceStateEventBody; import org.mockito.ArgumentCaptor; import org.mockito.MockedStatic; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import static org.assertj.core.api.Assertions.assertThat; import static org.kie.kogito.events.mongodb.codec.CodecUtils.ID; import static org.mockito.ArgumentMatchers.any; @@ -56,7 +55,7 @@ class UserTaskInstanceDataEventCodecTest { private UserTaskInstanceDataEventCodec codec; - private UserTaskInstanceDataEvent event; + private UserTaskInstanceStateDataEvent event; @BeforeEach void setUp() { @@ -66,59 +65,29 @@ void setUp() { String kogitoAddons = "testKogitoAddons"; String identity = "testIdentity"; - CommentEventBody comment = CommentEventBody.create() - .id("testCommentId") - .updatedBy("testCommentUpdatedBy") - .content("testCommentContent") - .updatedAt(new Date()) - .build(); - Set comments = Collections.singleton(comment); - AttachmentEventBody attachment = AttachmentEventBody.create() - .id("testAttachmentId") - .updatedBy("testAttachmentUpdatedBy") - .content(URI.create("test.attachment.test")) - .name("testAttachmentName") - .updatedAt(new Date()) - .build(); - Set attachments = Collections.singleton(attachment); - - Map metaData = new HashMap<>(); - metaData.put(ProcessInstanceEventBody.ID_META_DATA, "testKogitoProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.VERSION_META_DATA, "testKogitoProcessInstanceVersion"); - metaData.put(ProcessInstanceEventBody.ROOT_ID_META_DATA, "testKogitoRootProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.PROCESS_ID_META_DATA, "testKogitoProcessId"); - metaData.put(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA, "testKogitoRootProcessId"); - metaData.put(UserTaskInstanceEventBody.UT_STATE_META_DATA, "testKogitoUserTaskInstanceState"); - metaData.put(UserTaskInstanceEventBody.UT_ID_META_DATA, "testKogitoUserTaskInstanceId"); - - UserTaskInstanceEventBody body = UserTaskInstanceEventBody.create() - .id("testId") - .taskName("testTaskName") - .taskDescription("testTaskDescription") - .taskPriority("testTaskPriority") - .referenceName("testReferenceName") - .startDate(new Date()) - .completeDate(new Date()) + Map metaData = new HashMap<>(); + metaData.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, "testKogitoProcessInstanceId"); + metaData.put(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA, "testKogitoProcessInstanceVersion"); + metaData.put(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA, "testKogitoRootProcessInstanceId"); + metaData.put(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA, "testKogitoProcessId"); + metaData.put(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA, "testKogitoRootProcessId"); + metaData.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA, "testKogitoUserTaskInstanceState"); + metaData.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA, "testKogitoUserTaskInstanceId"); + + UserTaskInstanceStateEventBody body = UserTaskInstanceStateEventBody.create() + .userTaskInstanceId("testId") + .userTaskName("testTaskName") + .userTaskDescription("testTaskDescription") + .userTaskPriority("testTaskPriority") + .userTaskReferenceName("testReferenceName") + .eventDate(new Date()) .state("testState") .actualOwner("testActualOwner") - .potentialUsers(Collections.singleton("testPotentialUsers")) - .potentialGroups(Collections.singleton("testPotentialGroups")) - .excludedUsers(Collections.singleton("testExcludedUsers")) - .adminUsers(Collections.singleton("testAdminUsers")) - .adminGroups(Collections.singleton("testAdminGroups")) - .inputs(Collections.singletonMap("testInputsKey", "testInputsValue")) - .outputs(Collections.singletonMap("testOutputsKey", "testOutputsValue")) .processInstanceId("testKogitoProcessInstanceId") - .processInstanceVersion("testKogitoProcessInstanceVersion") - .rootProcessInstanceId("testKogitoRootProcessInstanceId") - .processId("testKogitoProcessId") - .rootProcessId("testKogitoRootProcessId") - .identity(identity) - .comments(comments) - .attachments(attachments) + .eventUser(identity) .build(); - event = new UserTaskInstanceDataEvent(source, kogitoAddons, identity, metaData, body); + event = new UserTaskInstanceStateDataEvent(source, kogitoAddons, identity, metaData, body); } @Test @@ -156,58 +125,35 @@ void encode() { verify(mockCodec, times(1)).encode(eq(writer), captor.capture(), eq(context)); Document doc = captor.getValue(); + Map node = new ObjectMapper().readValue(doc.toJson(), Map.class); + assertThat(doc).containsEntry(ID, event.getId()) .containsEntry("specversion", event.getSpecVersion().toString()) .containsEntry("source", event.getSource().toString()) .containsEntry("type", event.getType()) - .containsEntry("time", event.getTime()) - .containsEntry("subject", event.getSubject()) - .containsEntry("dataContentType", event.getDataContentType()) - .containsEntry("dataSchema", event.getDataSchema()) - .containsEntry("kogitoProcessinstanceId", event.getKogitoProcessInstanceId()) - .containsEntry("kogitoRootProcessinstanceId", event.getKogitoRootProcessInstanceId()) - .containsEntry("kogitoProcessId", event.getKogitoProcessId()) - .containsEntry("kogitoRootProcessId", event.getKogitoRootProcessId()) - .containsEntry("kogitoAddons", event.getKogitoAddons()) - .containsEntry("kogitoUserTaskinstanceId", event.getKogitoUserTaskinstanceId()) - .containsEntry("kogitoUserTaskinstanceState", event.getKogitoUserTaskinstanceState()) - .containsEntry("kogitoIdentity", event.getKogitoIdentity()); - - assertThat(((Document) doc.get("data"))).containsEntry("id", event.getData().getId()) - .containsEntry("taskName", event.getData().getTaskName()) - .containsEntry("taskDescription", event.getData().getTaskDescription()) - .containsEntry("taskPriority", event.getData().getTaskPriority()) - .containsEntry("referenceName", event.getData().getReferenceName()) - .containsEntry("startDate", event.getData().getStartDate()) - .containsEntry("completeDate", event.getData().getCompleteDate()) + .containsEntry("datacontenttype", event.getDataContentType()) + .containsEntry("kogitoprocinstanceid", event.getKogitoProcessInstanceId()) + .containsEntry("kogitoprocversion", event.getKogitoProcessInstanceVersion()) + .containsEntry("kogitorootprociid", event.getKogitoRootProcessInstanceId()) + .containsEntry("kogitoprocid", event.getKogitoProcessId()) + .containsEntry("kogitorootprocid", event.getKogitoRootProcessId()) + .containsEntry("kogitoaddons", event.getKogitoAddons()) + .containsEntry("kogitoidentity", event.getKogitoIdentity()) + .containsEntry("kogitousertaskiid", event.getKogitoUserTaskInstanceId()) + .containsEntry("kogitousertaskist", event.getKogitoUserTaskInstanceState()); + + assertThat(((Document) doc.get("data"))) + .containsEntry("userTaskName", event.getData().getUserTaskName()) + .containsEntry("userTaskDescription", event.getData().getUserTaskDescription()) + .containsEntry("userTaskPriority", event.getData().getUserTaskPriority()) + .containsEntry("userTaskReferenceName", event.getData().getUserTaskReferenceName()) .containsEntry("state", event.getData().getState()) .containsEntry("actualOwner", event.getData().getActualOwner()) - .containsEntry("potentialUsers", event.getData().getPotentialUsers()) - .containsEntry("potentialGroups", event.getData().getPotentialGroups()) - .containsEntry("excludedUsers", event.getData().getExcludedUsers()) - .containsEntry("adminUsers", event.getData().getAdminUsers()) - .containsEntry("adminGroups", event.getData().getAdminGroups()) - .containsEntry("inputs", new Document(event.getData().getInputs())) - .containsEntry("outputs", new Document(event.getData().getOutputs())) .containsEntry("processInstanceId", event.getData().getProcessInstanceId()) - .containsEntry("rootProcessInstanceId", event.getData().getRootProcessInstanceId()) - .containsEntry("identity", event.getData().getIdentity()) - .containsEntry("processId", event.getData().getProcessId()) - .containsEntry("rootProcessId", event.getData().getRootProcessId()); - - CommentEventBody c = event.getData().getComments().iterator().next(); - Document comment = new Document().append("id", c.getId()).append("content", c.getContent()) - .append("updatedAt", c.getUpdatedAt()).append("updatedBy", c.getUpdatedBy()); - Set comments = new HashSet<>(); - comments.add(comment); - assertThat(((Document) doc.get("data"))).containsEntry("comments", comments); - - AttachmentEventBody a = event.getData().getAttachments().iterator().next(); - Document attachment = new Document().append("id", a.getId()).append("content", a.getContent()) - .append("updatedAt", a.getUpdatedAt()).append("updatedBy", a.getUpdatedBy()).append("name", a.getName()); - Set attachments = new HashSet<>(); - attachments.add(attachment); - assertThat(((Document) doc.get("data"))).containsEntry("attachments", attachments); + .containsEntry("eventUser", event.getData().getEventUser()); + + } catch (JsonProcessingException e) { + e.printStackTrace(); } } diff --git a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/VariableInstanceDataEventCodecTest.java b/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/VariableInstanceDataEventCodecTest.java deleted file mode 100644 index a2003bf6467..00000000000 --- a/addons/common/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/codec/VariableInstanceDataEventCodecTest.java +++ /dev/null @@ -1,158 +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.events.mongodb.codec; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import org.bson.BsonReader; -import org.bson.BsonString; -import org.bson.BsonWriter; -import org.bson.Document; -import org.bson.codecs.Codec; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.EncoderContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; -import org.mockito.ArgumentCaptor; -import org.mockito.MockedStatic; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.kie.kogito.events.mongodb.codec.CodecUtils.ID; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -class VariableInstanceDataEventCodecTest { - - private VariableInstanceDataEventCodec codec; - - private VariableInstanceDataEvent event; - - @BeforeEach - void setUp() { - codec = new VariableInstanceDataEventCodec(); - - String source = "testSource"; - String kogitoAddons = "testKogitoAddons"; - - Map metaData = new HashMap<>(); - metaData.put(ProcessInstanceEventBody.ID_META_DATA, "testKogitoProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.VERSION_META_DATA, "testKogitoProcessInstanceVersion"); - metaData.put(ProcessInstanceEventBody.ROOT_ID_META_DATA, "testKogitoRootProcessInstanceId"); - metaData.put(ProcessInstanceEventBody.PROCESS_ID_META_DATA, "testKogitoProcessId"); - metaData.put(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA, "testKogitoRootProcessId"); - - VariableInstanceEventBody body = VariableInstanceEventBody.create() - .changeDate(new Date()) - .changedByNodeId("testChangedByNodeId") - .changedByNodeName("testChangedByNodeName") - .changedByNodeType("testChangedByNodeType") - .identity("testChangedByUser") - .processId("testKogitoProcessId") - .processInstanceId("testKogitoProcessInstanceId") - .rootProcessId("testKogitoRootProcessId") - .rootProcessInstanceId("testKogitoRootProcessInstanceId") - .variableName("testVariableName") - .variablePreviousValue("testVariablePreviousValue") - .variableValue("testVariableValue") - .build(); - - event = new VariableInstanceDataEvent(source, kogitoAddons, "identity", metaData, body); - } - - @Test - void generateIdIfAbsentFromDocument() { - assertThat(codec.generateIdIfAbsentFromDocument(event)).isEqualTo(event); - } - - @Test - void documentHasId() { - assertThat(codec.documentHasId(event)).isTrue(); - } - - @Test - void getDocumentId() { - assertThat(codec.getDocumentId(event)).isEqualTo(new BsonString(event.getId())); - } - - @Test - void decode() { - assertThat(codec.decode(mock(BsonReader.class), DecoderContext.builder().build())).isNull(); - } - - @Test - void encode() { - try (MockedStatic codecUtils = mockStatic(CodecUtils.class)) { - Codec mockCodec = mock(Codec.class); - codecUtils.when(CodecUtils::codec).thenReturn(mockCodec); - codecUtils.when(() -> CodecUtils.encodeDataEvent(any(), any())).thenCallRealMethod(); - BsonWriter writer = mock(BsonWriter.class); - EncoderContext context = EncoderContext.builder().build(); - - codec.encode(writer, event, context); - - ArgumentCaptor captor = ArgumentCaptor.forClass(Document.class); - verify(mockCodec, times(1)).encode(eq(writer), captor.capture(), eq(context)); - Document doc = captor.getValue(); - - assertThat(doc).containsEntry(ID, event.getId()) - .containsEntry("specversion", event.getSpecVersion().toString()) - .containsEntry("source", event.getSource().toString()) - .containsEntry("type", event.getType()) - .containsEntry("time", event.getTime()) - .containsEntry("subject", event.getSubject()) - .containsEntry("dataContentType", event.getDataContentType()) - .containsEntry("dataSchema", event.getDataSchema()) - .containsEntry("kogitoProcessinstanceId", event.getKogitoProcessInstanceId()) - .containsEntry("kogitoRootProcessinstanceId", event.getKogitoRootProcessInstanceId()) - .containsEntry("kogitoProcessId", event.getKogitoProcessId()) - .containsEntry("kogitoRootProcessId", event.getKogitoRootProcessId()) - .containsEntry("kogitoAddons", event.getKogitoAddons()) - .containsEntry("kogitoVariableName", event.getKogitoVariableName()) - .containsEntry("kogitoIdentity", event.getKogitoIdentity()); - - assertThat(((Document) doc.get("data"))).containsEntry("variableName", event.getData().getVariableName()) - .containsEntry("variableValue", event.getData().getVariableValue()) - .containsEntry("variablePreviousValue", event.getData().getVariablePreviousValue()) - .containsEntry("changeDate", event.getData().getChangeDate()) - .containsEntry("changedByNodeId", event.getData().getChangedByNodeId()) - .containsEntry("changedByNodeName", event.getData().getChangedByNodeName()) - .containsEntry("changedByNodeType", event.getData().getChangedByNodeType()) - .containsEntry("identity", event.getData().getIdentity()) - .containsEntry("processInstanceId", event.getData().getProcessInstanceId()) - .containsEntry("rootProcessInstanceId", event.getData().getRootProcessInstanceId()) - .containsEntry("processId", event.getData().getProcessId()) - .containsEntry("rootProcessId", event.getData().getRootProcessId()) - .containsEntry("identity", event.getData().getIdentity()); - } - } - - @Test - void getEncoderClass() { - assertThat(codec.getEncoderClass()).isEqualTo(VariableInstanceDataEvent.class); - } -} diff --git a/addons/common/human-task-prediction/api/src/main/java/org/kie/kogito/prediction/api/PredictionAwareHumanTaskLifeCycle.java b/addons/common/human-task-prediction/api/src/main/java/org/kie/kogito/prediction/api/PredictionAwareHumanTaskLifeCycle.java index 7957943f75f..77240e0f345 100644 --- a/addons/common/human-task-prediction/api/src/main/java/org/kie/kogito/prediction/api/PredictionAwareHumanTaskLifeCycle.java +++ b/addons/common/human-task-prediction/api/src/main/java/org/kie/kogito/prediction/api/PredictionAwareHumanTaskLifeCycle.java @@ -22,7 +22,7 @@ import java.util.Objects; import org.jbpm.process.instance.impl.humantask.BaseHumanTaskLifeCycle; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.workitem.Active; import org.jbpm.process.instance.impl.workitem.Complete; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; @@ -52,14 +52,14 @@ public Map transitionTo(KogitoWorkItem workItem, KogitoWorkItemM throw new InvalidLifeCyclePhaseException(transition.phase()); } - HumanTaskWorkItemImpl humanTaskWorkItem = (HumanTaskWorkItemImpl) workItem; + InternalHumanTaskWorkItem humanTaskWorkItem = (InternalHumanTaskWorkItem) workItem; if (targetPhase.id().equals(Active.ID)) { PredictionOutcome outcome = predictionService.predict(workItem, workItem.getParameters()); logger.debug("Prediction service returned confidence level {} for work item {}", outcome.getConfidenceLevel(), humanTaskWorkItem.getStringId()); if (outcome.isCertain()) { - humanTaskWorkItem.getResults().putAll(outcome.getData()); + humanTaskWorkItem.setResults(outcome.getData()); logger.debug("Prediction service is certain (confidence level {}) on the outputs, completing work item {}", outcome.getConfidenceLevel(), humanTaskWorkItem.getStringId()); ((InternalKogitoWorkItemManager) manager).internalCompleteWorkItem(humanTaskWorkItem); @@ -67,7 +67,7 @@ public Map transitionTo(KogitoWorkItem workItem, KogitoWorkItemM } else if (outcome.isPresent()) { logger.debug("Prediction service is NOT certain (confidence level {}) on the outputs, setting recommended outputs on work item {}", outcome.getConfidenceLevel(), humanTaskWorkItem.getStringId()); - humanTaskWorkItem.getResults().putAll(outcome.getData()); + humanTaskWorkItem.setResults(outcome.getData()); } } diff --git a/addons/common/mail/src/main/java/org/kie/kogito/mail/MailInfo.java b/addons/common/mail/src/main/java/org/kie/kogito/mail/MailInfo.java index 0b989493d73..3b82873327b 100644 --- a/addons/common/mail/src/main/java/org/kie/kogito/mail/MailInfo.java +++ b/addons/common/mail/src/main/java/org/kie/kogito/mail/MailInfo.java @@ -22,7 +22,7 @@ import java.util.Map; import java.util.Optional; -import org.kie.kogito.event.process.UserTaskDeadlineEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineEventBody; import org.mvel2.templates.TemplateRuntime; public class MailInfo { @@ -39,14 +39,14 @@ public class MailInfo { private String replyTo; private String body; - public static MailInfo of(UserTaskDeadlineEventBody data) { + public static MailInfo of(UserTaskInstanceDeadlineEventBody data) { Map info = data.getNotification(); return new MailInfo(Optional.ofNullable((String) info.get(TO_PROPERTY)).map(s -> s.split(",")).orElse(null), (String) info.get(FROM_PROPERTY), evalTemplate((String) info.get(SUBJECT_PROPERTY), data), (String) info.get(REPLY_TO_PROPERTY), evalTemplate((String) info.get(BODY_PROPERTY), data)); } - private static String evalTemplate(String template, UserTaskDeadlineEventBody data) { + private static String evalTemplate(String template, UserTaskInstanceDeadlineEventBody data) { return template != null ? TemplateRuntime.eval(template, data).toString() : null; } diff --git a/addons/common/mail/src/test/java/org/kie/kogito/mail/MailInfoTest.java b/addons/common/mail/src/test/java/org/kie/kogito/mail/MailInfoTest.java index a97ec2c70c2..bc16a786516 100644 --- a/addons/common/mail/src/test/java/org/kie/kogito/mail/MailInfoTest.java +++ b/addons/common/mail/src/test/java/org/kie/kogito/mail/MailInfoTest.java @@ -18,12 +18,11 @@ */ package org.kie.kogito.mail; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.UserTaskDeadlineEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineEventBody; import static org.assertj.core.api.Assertions.assertThat; @@ -33,12 +32,14 @@ public class MailInfoTest { public void testMailInfo() { Map notification = new HashMap<>(); notification.put(MailInfo.SUBJECT_PROPERTY, "${inputs.name}"); - notification.put(MailInfo.BODY_PROPERTY, "My name for process ${processInstanceId} is ${inputs.name}"); + notification.put(MailInfo.BODY_PROPERTY, "My name for process ${inputs.processInstanceId} is ${inputs.name}"); notification.put(MailInfo.FROM_PROPERTY, "javierito"); notification.put(MailInfo.TO_PROPERTY, "javierito@doesnotexist.com,fulanito@doesnotexist.com"); notification.put(MailInfo.REPLY_TO_PROPERTY, "javierito@doesnotexist.com"); - MailInfo mailInfo = MailInfo.of(UserTaskDeadlineEventBody.create("1", notification).inputs(Collections - .singletonMap("name", "Javierito")).processInstanceId("1").build()); + MailInfo mailInfo = MailInfo.of(UserTaskInstanceDeadlineEventBody.create() + .notification(notification) + .inputs(Map.of("name", "Javierito", "processInstanceId", "1")) + .build()); assertThat(mailInfo.subject()).isEqualTo("Javierito"); assertThat(mailInfo.body()).isEqualTo("My name for process 1 is Javierito"); assertThat(mailInfo.from()).isEqualTo("javierito"); diff --git a/addons/common/messaging/src/test/java/org/kie/kogito/addon/cloudevents/CloudEventConverterTest.java b/addons/common/messaging/src/test/java/org/kie/kogito/addon/cloudevents/CloudEventConverterTest.java index eb0eaf0c915..8dcaf332c78 100644 --- a/addons/common/messaging/src/test/java/org/kie/kogito/addon/cloudevents/CloudEventConverterTest.java +++ b/addons/common/messaging/src/test/java/org/kie/kogito/addon/cloudevents/CloudEventConverterTest.java @@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test; import org.kie.kogito.event.cloudevents.CloudEventExtensionConstants; -import org.kie.kogito.event.process.ProcessDataEvent; +import org.kie.kogito.event.process.ProcessInstanceDataEvent; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -122,7 +122,7 @@ void verifyDataEventWithProcessDataCloudEventConversion() throws IOException { .contains("12345"); } - public static class PersonDataEvent extends ProcessDataEvent { + public static class PersonDataEvent extends ProcessInstanceDataEvent { private String kogitoStartFromNode; diff --git a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java index 9c3f51d3b3a..30409c0f6a8 100644 --- a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java +++ b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java @@ -33,6 +33,7 @@ import org.kie.kogito.process.workitem.InvalidLifeCyclePhaseException; import org.kie.kogito.process.workitem.InvalidTransitionException; import org.kie.kogito.process.workitem.NotAuthorizedException; +import org.kie.kogito.process.workitem.WorkItemExecutionException; public abstract class BaseExceptionsHandler { @@ -48,9 +49,9 @@ public abstract class BaseExceptionsHandler { private static class FunctionHolder { private final Function contentGenerator; - private final Function responseGenerator; + private final Function> responseGenerator; - public FunctionHolder(Function contentGenerator, Function responseGenerator) { + public FunctionHolder(Function contentGenerator, Function> responseGenerator) { this.contentGenerator = contentGenerator; this.responseGenerator = responseGenerator; } @@ -59,20 +60,20 @@ public Function getContentGenerator() { return contentGenerator; } - public Function getResponseGenerator() { + public Function> getResponseGenerator() { return responseGenerator; } } - private final FunctionHolder defaultHolder = new FunctionHolder<>(ex -> ex, BaseExceptionsHandler.this::internalError); + private final FunctionHolder defaultHolder = new FunctionHolder<>(ex -> ex, ex -> BaseExceptionsHandler.this::internalError); protected BaseExceptionsHandler() { mapper = new HashMap<>(); mapper.put(InvalidLifeCyclePhaseException.class, new FunctionHolder<>( - ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), BaseExceptionsHandler.this::badRequest)); + ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex -> BaseExceptionsHandler.this::badRequest)); mapper.put(InvalidTransitionException.class, new FunctionHolder<>( - ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), BaseExceptionsHandler.this::badRequest)); + ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex -> BaseExceptionsHandler.this::badRequest)); mapper.put(NodeInstanceNotFoundException.class, new FunctionHolder<>( ex -> { @@ -82,7 +83,7 @@ protected BaseExceptionsHandler() { response.put(PROCESS_INSTANCE_ID, exception.getProcessInstanceId()); response.put(NODE_INSTANCE_ID, exception.getNodeInstanceId()); return response; - }, BaseExceptionsHandler.this::notFound)); + }, ex -> BaseExceptionsHandler.this::notFound)); mapper.put(NodeNotFoundException.class, new FunctionHolder<>( ex -> { @@ -92,10 +93,10 @@ protected BaseExceptionsHandler() { response.put(PROCESS_INSTANCE_ID, exception.getProcessInstanceId()); response.put(NODE_ID, exception.getNodeId()); return response; - }, BaseExceptionsHandler.this::notFound)); + }, ex -> BaseExceptionsHandler.this::notFound)); mapper.put(NotAuthorizedException.class, new FunctionHolder<>( - ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), BaseExceptionsHandler.this::forbidden)); + ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex -> BaseExceptionsHandler.this::forbidden)); mapper.put(ProcessInstanceDuplicatedException.class, new FunctionHolder<>( ex -> { @@ -104,7 +105,7 @@ protected BaseExceptionsHandler() { response.put(MESSAGE, exception.getMessage()); response.put(PROCESS_INSTANCE_ID, exception.getProcessInstanceId()); return response; - }, BaseExceptionsHandler.this::conflict)); + }, ex -> BaseExceptionsHandler.this::conflict)); mapper.put(ProcessInstanceExecutionException.class, new FunctionHolder<>( ex -> { @@ -114,7 +115,7 @@ protected BaseExceptionsHandler() { response.put(FAILED_NODE_ID, exception.getFailedNodeId()); response.put(MESSAGE, exception.getErrorMessage()); return response; - }, BaseExceptionsHandler.this::internalError)); + }, ex -> BaseExceptionsHandler.this::internalError)); mapper.put(ProcessInstanceNotFoundException.class, new FunctionHolder<>( ex -> { @@ -123,12 +124,12 @@ protected BaseExceptionsHandler() { response.put(MESSAGE, exception.getMessage()); response.put(PROCESS_INSTANCE_ID, exception.getProcessInstanceId()); return response; - }, BaseExceptionsHandler.this::notFound)); + }, ex -> BaseExceptionsHandler.this::notFound)); mapper.put(WorkItemNotFoundException.class, new FunctionHolder<>(ex -> { WorkItemNotFoundException exception = (WorkItemNotFoundException) ex; return Map.of(MESSAGE, exception.getMessage(), TASK_ID, exception.getWorkItemId()); - }, BaseExceptionsHandler.this::notFound)); + }, ex -> BaseExceptionsHandler.this::notFound)); mapper.put(VariableViolationException.class, new FunctionHolder<>( ex -> { @@ -138,9 +139,28 @@ protected BaseExceptionsHandler() { response.put(PROCESS_INSTANCE_ID, exception.getProcessInstanceId()); response.put(VARIABLE, exception.getVariableName()); return response; - }, BaseExceptionsHandler.this::badRequest)); + }, ex -> BaseExceptionsHandler.this::badRequest)); - mapper.put(IllegalArgumentException.class, new FunctionHolder<>(ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), BaseExceptionsHandler.this::badRequest)); + mapper.put(WorkItemExecutionException.class, new FunctionHolder<>( + ex -> Map.of(MESSAGE, ex.getMessage()), + ex -> fromErrorCode(((WorkItemExecutionException) ex).getErrorCode()))); + + mapper.put(IllegalArgumentException.class, new FunctionHolder<>(ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex -> BaseExceptionsHandler.this::badRequest)); + } + + private Function fromErrorCode(String errorCode) { + switch (errorCode) { + case "400": + return this::badRequest; + case "403": + return this::forbidden; + case "404": + return this::notFound; + case "409": + return this::conflict; + default: + return this::internalError; + } } protected abstract T badRequest(R body); @@ -156,8 +176,8 @@ protected BaseExceptionsHandler() { public T mapException(R exception) { FunctionHolder holder = (FunctionHolder) mapper.getOrDefault(exception.getClass(), defaultHolder); U body = holder.getContentGenerator().apply(exception); - if (exception instanceof ProcessInstanceExecutionException) { - Throwable rootCause = ((ProcessInstanceExecutionException) exception).getCause(); + if (exception instanceof ProcessInstanceExecutionException || exception instanceof WorkItemExecutionException) { + Throwable rootCause = exception.getCause(); while (rootCause != null) { if (mapper.containsKey(rootCause.getClass())) { @@ -167,6 +187,6 @@ public T mapException(R exception) { rootCause = rootCause.getCause(); } } - return holder.getResponseGenerator().apply(body); + return holder.getResponseGenerator().apply(exception).apply(body); } } diff --git a/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java b/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java index 0e249a4ebc3..7e385e2183b 100644 --- a/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java +++ b/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java @@ -30,6 +30,7 @@ import org.kie.kogito.process.workitem.InvalidLifeCyclePhaseException; import org.kie.kogito.process.workitem.InvalidTransitionException; import org.kie.kogito.process.workitem.NotAuthorizedException; +import org.kie.kogito.process.workitem.WorkItemExecutionException; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -140,4 +141,14 @@ void testMapVariableViolationException() { "message")); assertThat(response).isEqualTo(badRequestResponse); } + + @Test + void testMapWorkItemExecutionException() { + assertThat(tested.mapException(new WorkItemExecutionException("400", "message"))).isEqualTo(badRequestResponse); + assertThat(tested.mapException(new WorkItemExecutionException("404", "message"))).isEqualTo(notFoundResponse); + assertThat(tested.mapException(new WorkItemExecutionException("403", "message"))).isEqualTo(forbiddenResponse); + assertThat(tested.mapException(new WorkItemExecutionException("409", "message"))).isEqualTo(conflictResponse); + assertThat(tested.mapException(new WorkItemExecutionException("500", "message"))).isEqualTo(internalErrorResponse); + assertThat(tested.mapException(new WorkItemExecutionException("One error code"))).isEqualTo(internalErrorResponse); + } } diff --git a/addons/common/task-management/src/main/java/org/kie/kogito/task/management/service/TaskManagementService.java b/addons/common/task-management/src/main/java/org/kie/kogito/task/management/service/TaskManagementService.java index 3636702148e..964d26646e6 100644 --- a/addons/common/task-management/src/main/java/org/kie/kogito/task/management/service/TaskManagementService.java +++ b/addons/common/task-management/src/main/java/org/kie/kogito/task/management/service/TaskManagementService.java @@ -25,7 +25,7 @@ import java.util.function.Supplier; import org.jbpm.process.instance.impl.humantask.HumanTaskHelper; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessConfig; @@ -57,7 +57,7 @@ public TaskInfo updateTask(String processId, KogitoWorkItem workItem = UnitOfWorkExecutor.executeInUnitOfWork(processConfig.unitOfWorkManager(), () -> pi.updateWorkItem(taskId, wi -> { - HumanTaskWorkItemImpl humanTask = HumanTaskHelper.asHumanTask(wi); + InternalHumanTaskWorkItem humanTask = HumanTaskHelper.asHumanTask(wi); setField(humanTask::setAdminGroups, taskInfo::getAdminGroups, shouldReplace); setField(humanTask::setAdminUsers, taskInfo::getAdminUsers, shouldReplace); setField(humanTask::setExcludedUsers, taskInfo::getExcludedUsers, shouldReplace); diff --git a/api/kogito-api/src/main/java/org/kie/kogito/event/EventPublisher.java b/api/kogito-api/src/main/java/org/kie/kogito/event/EventPublisher.java index 0869447738c..8a28f56d81b 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/event/EventPublisher.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/event/EventPublisher.java @@ -31,6 +31,10 @@ */ public interface EventPublisher { + String PROCESS_INSTANCES_TOPIC_NAME = "kogito-processinstances-events"; + String USER_TASK_INSTANCES_TOPIC_NAME = "kogito-usertaskinstances-events"; + String PROCESS_DEFINITIONS_TOPIC_NAME = "kogito-processdefinitions-events"; + /** * Publishes individual event * diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventListener.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventListener.java index d1a1112d69d..fdb2fd88d25 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventListener.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventListener.java @@ -19,6 +19,12 @@ package org.kie.kogito.internal.process.event; import org.kie.api.event.process.ProcessEventListener; +import org.kie.api.event.usertask.UserTaskAssignmentEvent; +import org.kie.api.event.usertask.UserTaskAttachmentEvent; +import org.kie.api.event.usertask.UserTaskCommentEvent; +import org.kie.api.event.usertask.UserTaskDeadlineEvent; +import org.kie.api.event.usertask.UserTaskStateEvent; +import org.kie.api.event.usertask.UserTaskVariableEvent; public interface KogitoProcessEventListener extends ProcessEventListener { @@ -38,6 +44,49 @@ default void beforeWorkItemTransition(ProcessWorkItemTransitionEvent event) { default void afterWorkItemTransition(ProcessWorkItemTransitionEvent event) { } - default void onHumanTaskDeadline(HumanTaskDeadlineEvent event) { + // for user tasks + + default void onUserTaskDeadline(UserTaskDeadlineEvent event) { + // nothing + } + + default void onUserTaskState(UserTaskStateEvent event) { + // nothing + } + + default void onUserTaskAssignment(UserTaskAssignmentEvent event) { + // nothing + } + + default void onUserTaskInputVariable(UserTaskVariableEvent event) { + // nothing + } + + default void onUserTaskOutputVariable(UserTaskVariableEvent event) { + // nothing + } + + default void onUserTaskAttachmentAdded(UserTaskAttachmentEvent event) { + // nothing + } + + default void onUserTaskAttachmentDeleted(UserTaskAttachmentEvent event) { + // nothing + } + + default void onUserTaskAttachmentChange(UserTaskAttachmentEvent event) { + // nothing + } + + default void onUserTaskCommentChange(UserTaskCommentEvent event) { + // nothing + } + + default void onUserTaskCommentAdded(UserTaskCommentEvent event) { + // nothing + } + + default void onUserTaskCommentDeleted(UserTaskCommentEvent event) { + // nothing } } diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventSupport.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventSupport.java index e6d481489e8..d0a2bc155c2 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventSupport.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/KogitoProcessEventSupport.java @@ -20,11 +20,14 @@ import java.util.List; import java.util.Map; +import java.util.Set; import org.kie.api.runtime.KieRuntime; import org.kie.kogito.internal.process.runtime.KogitoNodeInstance; import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; +import org.kie.kogito.process.workitem.Attachment; +import org.kie.kogito.process.workitem.Comment; import org.kie.kogito.process.workitem.HumanTaskWorkItem; import org.kie.kogito.process.workitem.Transition; @@ -68,19 +71,99 @@ void fireAfterVariableChanged(String name, String id, Object oldValue, Object ne void fireOnMessage(KogitoProcessInstance instance, KogitoNodeInstance nodeInstance, KieRuntime kruntime, String messageName, Object messageObject); - void fireOnTaskNotStartedDeadline(KogitoProcessInstance instance, + // user tasks events + + void fireOneUserTaskStateChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + String oldPhaseStatus, String newPhaseStatus); + + void fireOnUserTaskNotStartedDeadline( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, HumanTaskWorkItem workItem, Map notification, KieRuntime kruntime); - void fireOnTaskNotCompletedDeadline(KogitoProcessInstance instance, + void fireOnUserTaskNotCompletedDeadline( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, HumanTaskWorkItem workItem, Map notification, KieRuntime kruntime); + enum AssignmentType { + USER_OWNERS, + USER_GROUPS, + USERS_EXCLUDED, + ADMIN_GROUPS, + ADMIN_USERS + }; + + void fireOnUserTaskAssignmentChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + AssignmentType assignmentType, + Set oldUsersId, Set newUsersId); + + void fireOnUserTaskInputVariableChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + String variableName, + Object newValue, Object oldValue); + + void fireOnUserTaskOutputVariableChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + String variableName, + Object newValue, Object oldValue); + + void fireOnUserTaskAttachmentAdded( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Attachment addedAttachment); + + void fireOnUserTaskAttachmentDeleted( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Attachment deletedAttachment); + + void fireOnUserTaskAttachmentChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Attachment oldAttachment, Attachment newAttachment); + + void fireOnUserTaskCommentChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Comment oldComment, Comment newComment); + + void fireOnUserTaskCommentDeleted( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Comment deletedComment); + + void fireOnUserTaskCommentAdded( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Comment addedComment); + + // + void reset(); void addEventListener(KogitoProcessEventListener listener); void removeEventListener(KogitoProcessEventListener listener); + } \ No newline at end of file diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNode.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNode.java index 67926f5d9fb..f15769da3de 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNode.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNode.java @@ -24,4 +24,6 @@ public interface KogitoNode extends Node { NodeContainer getParentContainer(); + + String getUniqueId(); } diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java index 718974764f4..f91e8b1957f 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java @@ -24,6 +24,19 @@ public interface KogitoNodeInstance extends NodeInstance { + enum CancelType { + OBSOLETE, + ABORTED, + SKIPPED, + ERROR + } + + default boolean isCancelled() { + return getCancelType() != null; + } + + CancelType getCancelType(); + /** * The id of the node instance. This is unique within the * node instance container this node instance lives in. diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/utils/ConversionUtils.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/utils/ConversionUtils.java index ef750c4120a..ee0a4a64234 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/internal/utils/ConversionUtils.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/utils/ConversionUtils.java @@ -43,7 +43,7 @@ public static T convert(Object value, Class clazz) { /** * Converts a string into a list of objects using `,` as a separator - * + * * @param * @param value object to be converted into list * @param clazz the item target class @@ -55,7 +55,7 @@ public static Collection convertToCollection(Object value, Class clazz /** * Converts a string into a list of objects - * + * * @param * @param value object to be converted into list * @param clazz the item target class @@ -71,7 +71,7 @@ public static Collection convertToCollection(Object value, Class clazz /** * Converts an object to an instance of the provided class - * + * * @param * @param value * @param clazz @@ -81,6 +81,8 @@ public static Collection convertToCollection(Object value, Class clazz public static T convert(Object value, Class clazz, Function stringConverter) { if (value == null || clazz.isAssignableFrom(value.getClass())) { return clazz.cast(value); + } else if (isConvertibleFromStringJavaBaseType(clazz)) { + return convertFromStringJavaBaseType(clazz, stringConverter.apply(value)); } else { Method convert = getConvertMethod(clazz); if (convert != null) { @@ -114,9 +116,48 @@ private static Method getConvertMethod(Class clazz) { return null; } + /** + * @return true if the given type corresponds to a java base type that has the method valueOf(String value). + */ + private static boolean isConvertibleFromStringJavaBaseType(Class clazz) { + return clazz == Short.class || clazz == Integer.class || clazz == Long.class || clazz == Byte.class || + clazz == Float.class || clazz == Double.class || + clazz == Boolean.class; + } + + /** + * @return the value created by applying the static method valueOf(String) on the given class. We use this method on + * these base java types to ensure conversion continues working on code generated by the quarkus native build, + * since it was detected that valueOf is not discovered by reflection on these classes after the native build. + */ + private static T convertFromStringJavaBaseType(Class clazz, String value) throws NumberFormatException { + if (clazz == Short.class) { + return (T) Short.valueOf(value); + } + if (clazz == Integer.class) { + return (T) Integer.valueOf(value); + } + if (clazz == Long.class) { + return (T) Long.valueOf(value); + } + if (clazz == Byte.class) { + return (T) Byte.valueOf(value); + } + if (clazz == Float.class) { + return (T) Float.valueOf(value); + } + if (clazz == Double.class) { + return (T) Double.valueOf(value); + } + if (clazz == Boolean.class) { + return (T) Boolean.valueOf(value); + } + throw new IllegalArgumentException("This method can not be applied to this class: " + clazz); + } + /** * Convert to camel case - * + * * @param text * @return */ @@ -147,7 +188,7 @@ public static String toCamelCase(String text) { /** * Concatenate two paths using / as separator - * + * * @param onePath * @param anotherPath * @return @@ -158,7 +199,7 @@ public static String concatPaths(String onePath, String anotherPath) { /** * Concatenate two paths using a separator - * + * * @param onePath * @param anotherPath * @param concatChars separator to use @@ -182,7 +223,7 @@ public static String concatPaths(String onePath, String anotherPath, String conc /** * Check empty string - * + * * @param value * @return */ @@ -220,4 +261,17 @@ public static String sanitizeJavaName(String name, boolean capitalize) { } return sb.toString(); } + + /** + * Receives a String possibly with FQDN org.acme.ProcessTest1 and returns a simple name like ProcessTest1 + * + * @param processId a possible FQDN + * @return simple name + */ + public static String sanitizeToSimpleName(String processId) { + if (Objects.isNull(processId)) { + return null; + } + return processId.substring(processId.lastIndexOf('.') + 1); + } } diff --git a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Attachment.java b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Attachment.java index e4a56750af6..737de03fdfb 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Attachment.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Attachment.java @@ -22,6 +22,7 @@ public class Attachment extends TaskMetaEntity { + private static final long serialVersionUID = 1L; private String name; public Attachment(String id, String user) { @@ -35,4 +36,9 @@ public String getName() { public void setName(String name) { this.name = name; } + + @Override + public Attachment clone() throws CloneNotSupportedException { + return (Attachment) super.clone(); + } } diff --git a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Comment.java b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Comment.java index d946395476b..237fc0c0cdf 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Comment.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/Comment.java @@ -23,4 +23,9 @@ public class Comment extends TaskMetaEntity { public Comment(String id, String user) { super(id, user); } + + @Override + public Comment clone() throws CloneNotSupportedException { + return (Comment) super.clone(); + } } diff --git a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java index 89328b72161..84f07f496ab 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java @@ -21,7 +21,7 @@ import java.io.Serializable; import java.util.Date; -public class TaskMetaEntity implements Serializable { +public class TaskMetaEntity implements Serializable, Cloneable { private static final long serialVersionUID = 1L; private K id; diff --git a/api/kogito-api/src/main/java/org/kie/kogito/uow/events/UnitOfWorkProcessEventListener.java b/api/kogito-api/src/main/java/org/kie/kogito/uow/events/UnitOfWorkProcessEventListener.java index 183654a65c9..e2998dfc5ab 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/uow/events/UnitOfWorkProcessEventListener.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/uow/events/UnitOfWorkProcessEventListener.java @@ -27,8 +27,14 @@ import org.kie.api.event.process.ProcessVariableChangedEvent; import org.kie.api.event.process.SLAViolatedEvent; import org.kie.api.event.process.SignalEvent; +import org.kie.api.event.usertask.UserTaskAssignmentEvent; +import org.kie.api.event.usertask.UserTaskAttachmentEvent; +import org.kie.api.event.usertask.UserTaskCommentEvent; +import org.kie.api.event.usertask.UserTaskDeadlineEvent; +import org.kie.api.event.usertask.UserTaskEvent; +import org.kie.api.event.usertask.UserTaskStateEvent; +import org.kie.api.event.usertask.UserTaskVariableEvent; import org.kie.kogito.internal.process.event.DefaultKogitoProcessEventListener; -import org.kie.kogito.internal.process.event.HumanTaskDeadlineEvent; import org.kie.kogito.internal.process.event.ProcessWorkItemTransitionEvent; import org.kie.kogito.uow.UnitOfWorkManager; import org.kie.kogito.uow.WorkUnit; @@ -46,9 +52,14 @@ private void intercept(ProcessEvent event) { })); } + private void intercept(UserTaskEvent event) { + unitOfWorkManager.currentUnitOfWork().intercept(WorkUnit.create(event, e -> { + })); + } + @Override public void beforeProcessStarted(ProcessStartedEvent event) { - intercept(event); + } @Override @@ -58,7 +69,7 @@ public void afterProcessStarted(ProcessStartedEvent event) { @Override public void beforeProcessCompleted(ProcessCompletedEvent event) { - intercept(event); + } @Override @@ -73,12 +84,12 @@ public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) { @Override public void afterNodeTriggered(ProcessNodeTriggeredEvent event) { - intercept(event); + } @Override public void beforeNodeLeft(ProcessNodeLeftEvent event) { - intercept(event); + } @Override @@ -88,7 +99,7 @@ public void afterNodeLeft(ProcessNodeLeftEvent event) { @Override public void beforeVariableChanged(ProcessVariableChangedEvent event) { - intercept(event); + } @Override @@ -103,12 +114,12 @@ public void beforeSLAViolated(SLAViolatedEvent event) { @Override public void afterSLAViolated(SLAViolatedEvent event) { - intercept(event); + } @Override public void beforeWorkItemTransition(ProcessWorkItemTransitionEvent event) { - intercept(event); + } @Override @@ -126,8 +137,59 @@ public void onMessage(MessageEvent event) { intercept(event); } + // user tasks + @Override + public void onUserTaskDeadline(UserTaskDeadlineEvent event) { + intercept(event); + } + + @Override + public void onUserTaskState(UserTaskStateEvent event) { + intercept(event); + } + + @Override + public void onUserTaskAssignment(UserTaskAssignmentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskAttachmentAdded(UserTaskAttachmentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskAttachmentChange(UserTaskAttachmentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskAttachmentDeleted(UserTaskAttachmentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskCommentAdded(UserTaskCommentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskCommentChange(UserTaskCommentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskCommentDeleted(UserTaskCommentEvent event) { + intercept(event); + } + + @Override + public void onUserTaskInputVariable(UserTaskVariableEvent event) { + intercept(event); + } + @Override - public void onHumanTaskDeadline(HumanTaskDeadlineEvent event) { + public void onUserTaskOutputVariable(UserTaskVariableEvent event) { intercept(event); } diff --git a/api/kogito-api/src/test/java/org/kie/kogito/internal/utils/ConversionUtilsTest.java b/api/kogito-api/src/test/java/org/kie/kogito/internal/utils/ConversionUtilsTest.java index 3b2d6b7993f..43f1cc41534 100644 --- a/api/kogito-api/src/test/java/org/kie/kogito/internal/utils/ConversionUtilsTest.java +++ b/api/kogito-api/src/test/java/org/kie/kogito/internal/utils/ConversionUtilsTest.java @@ -27,6 +27,7 @@ import static org.kie.kogito.internal.utils.ConversionUtils.concatPaths; import static org.kie.kogito.internal.utils.ConversionUtils.convert; import static org.kie.kogito.internal.utils.ConversionUtils.convertToCollection; +import static org.kie.kogito.internal.utils.ConversionUtils.sanitizeToSimpleName; import static org.kie.kogito.internal.utils.ConversionUtils.toCamelCase; class ConversionUtilsTest { @@ -138,4 +139,15 @@ public void testConcatPaths() { public void testConvertToCollection() { assertThat(convertToCollection("1,2,3", Integer.class)).isEqualTo(Arrays.asList(1, 2, 3)); } + + @Test + public void testSanitizeToSimpleName() { + String nameFull = "org.acme.ProcessTest1"; + String nameSimple = "ProcessTest2"; + String nameEmpty = ""; + assertThat(sanitizeToSimpleName(nameFull)).isEqualTo("ProcessTest1"); + assertThat(sanitizeToSimpleName(nameSimple)).isEqualTo("ProcessTest2"); + assertThat(sanitizeToSimpleName(nameEmpty)).isEqualTo(""); + assertThat(sanitizeToSimpleName(null)).isNull(); + } } diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/AttachmentEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/AttachmentEventBody.java deleted file mode 100644 index e2a6476f564..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/AttachmentEventBody.java +++ /dev/null @@ -1,128 +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.event.process; - -import java.net.URI; -import java.util.Date; -import java.util.Objects; - -public class AttachmentEventBody { - - private String id; - private String name; - private URI content; - private Date updatedAt; - private String updatedBy; - - private AttachmentEventBody() { - } - - public static Builder create() { - return new Builder(new AttachmentEventBody()); - } - - public URI getContent() { - return content; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public String getUpdatedBy() { - return updatedBy; - } - - public String getId() { - return id; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "AttachmentEventBody{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - ", content=" + content + - ", updatedAt=" + updatedAt + - ", updatedBy='" + updatedBy + '\'' + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - AttachmentEventBody that = (AttachmentEventBody) o; - return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(content, that.content) && Objects.equals(updatedAt, that.updatedAt) - && Objects.equals(updatedBy, that.updatedBy); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, content, updatedAt, updatedBy); - } - - public Builder update() { - return new Builder(this); - } - - public static class Builder { - - private AttachmentEventBody instance; - - private Builder(AttachmentEventBody instance) { - this.instance = instance; - } - - public Builder id(String id) { - instance.id = id; - return this; - } - - public Builder name(String name) { - instance.name = name; - return this; - } - - public Builder content(URI content) { - instance.content = content; - return this; - } - - public Builder updatedBy(String updatedBy) { - instance.updatedBy = updatedBy; - return this; - } - - public Builder updatedAt(Date updatedAt) { - instance.updatedAt = updatedAt; - return this; - } - - public AttachmentEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/CommentEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/CommentEventBody.java deleted file mode 100644 index 984dd844cc0..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/CommentEventBody.java +++ /dev/null @@ -1,116 +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.event.process; - -import java.util.Date; -import java.util.Objects; - -public class CommentEventBody { - - private String id; - private String content; - private Date updatedAt; - private String updatedBy; - - private CommentEventBody() { - } - - public static Builder create() { - return new Builder(new CommentEventBody()); - } - - public String getContent() { - return content; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public String getUpdatedBy() { - return updatedBy; - } - - public String getId() { - return id; - } - - @Override - public String toString() { - return "CommentEventBody{" + - "id='" + id + '\'' + - ", content='" + content + '\'' + - ", updatedAt=" + updatedAt + - ", updatedBy='" + updatedBy + '\'' + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - CommentEventBody that = (CommentEventBody) o; - return Objects.equals(id, that.id) && Objects.equals(content, that.content) && Objects.equals(updatedAt, that.updatedAt) && Objects.equals(updatedBy, - that.updatedBy); - } - - @Override - public int hashCode() { - return Objects.hash(id, content, updatedAt, updatedBy); - } - - public Builder update() { - return new Builder(this); - } - - public static class Builder { - - private CommentEventBody instance; - - private Builder(CommentEventBody instance) { - this.instance = instance; - } - - public Builder id(String id) { - instance.id = id; - return this; - } - - public Builder content(String content) { - instance.content = content; - return this; - } - - public Builder updatedBy(String updatedBy) { - instance.updatedBy = updatedBy; - return this; - } - - public Builder updatedAt(Date updatedAt) { - instance.updatedAt = updatedAt; - return this; - } - - public CommentEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/MilestoneEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/MilestoneEventBody.java deleted file mode 100644 index 9f03a31f3e6..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/MilestoneEventBody.java +++ /dev/null @@ -1,107 +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.event.process; - -import java.util.Objects; - -public class MilestoneEventBody { - - private String id; - private String name; - private String status; - - private MilestoneEventBody() { - } - - public static Builder create() { - return new Builder(new MilestoneEventBody()); - } - - public String getName() { - return name; - } - - public String getStatus() { - return status; - } - - public String getId() { - return id; - } - - @Override - public String toString() { - return "MilestoneEventBody{" + - "name='" + name + '\'' + - ", status='" + status + '\'' + - ", id='" + id + '\'' + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof MilestoneEventBody)) { - return false; - } - MilestoneEventBody that = (MilestoneEventBody) o; - return getId().equals(that.getId()) && - getName().equals(that.getName()) && - getStatus().equals(that.getStatus()); - } - - @Override - public int hashCode() { - return Objects.hash(getId(), getName(), getStatus()); - } - - public Builder update() { - return new Builder(this); - } - - public static class Builder { - - private MilestoneEventBody instance; - - private Builder(MilestoneEventBody instance) { - this.instance = instance; - } - - public Builder id(String id) { - instance.id = id; - return this; - } - - public Builder name(String name) { - instance.name = name; - return this; - } - - public Builder status(String status) { - instance.status = status; - return this; - } - - public MilestoneEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/NodeDefinition.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/NodeDefinition.java new file mode 100644 index 00000000000..bfae93f1da6 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/NodeDefinition.java @@ -0,0 +1,101 @@ +/* + * 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.event.process; + +import java.util.Map; + +public class NodeDefinition { + private String id; + private String name; + private String type; + private String uniqueId; + private Map metadata; + + public NodeDefinition() { + } + + public NodeDefinition(String id, String name, String type, String uniqueId, Map metadata) { + this.id = id; + this.name = name; + this.type = type; + this.uniqueId = uniqueId; + this.metadata = metadata; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public String getUniqueId() { + return uniqueId; + } + + public Map getMetadata() { + return metadata; + } + + public static NodeDefinitionEventBodyBuilder builder() { + return new NodeDefinitionEventBodyBuilder(); + } + + public static class NodeDefinitionEventBodyBuilder { + private String id; + private String name; + private String type; + private String uniqueId; + private Map metadata; + + public NodeDefinitionEventBodyBuilder setId(String id) { + this.id = id; + return this; + } + + public NodeDefinitionEventBodyBuilder setName(String name) { + this.name = name; + return this; + } + + public NodeDefinitionEventBodyBuilder setType(String type) { + this.type = type; + return this; + } + + public NodeDefinitionEventBodyBuilder setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + return this; + } + + public NodeDefinitionEventBodyBuilder setMetadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public NodeDefinition build() { + return new NodeDefinition(id, name, type, uniqueId, metadata); + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/NodeInstanceEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/NodeInstanceEventBody.java deleted file mode 100644 index c20303f89ba..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/NodeInstanceEventBody.java +++ /dev/null @@ -1,149 +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.event.process; - -import java.util.Date; - -public class NodeInstanceEventBody { - - private String id; - private String nodeId; - private String nodeDefinitionId; - private String nodeName; - private String nodeType; - private Date triggerTime; - private Date leaveTime; - - private NodeInstanceEventBody() { - } - - public String getId() { - return id; - } - - public String getNodeId() { - return nodeId; - } - - public String getNodeDefinitionId() { - return nodeDefinitionId; - } - - public String getNodeName() { - return nodeName; - } - - public String getNodeType() { - return nodeType; - } - - public Date getTriggerTime() { - return triggerTime; - } - - public Date getLeaveTime() { - return leaveTime; - } - - @Override - public String toString() { - return "NodeInstance [id=" + id + ", nodeId=" + nodeId + ", nodeName=" + nodeName + ", nodeType=" + nodeType + ", triggerTime=" + triggerTime + ", leaveTime=" + leaveTime + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NodeInstanceEventBody other = (NodeInstanceEventBody) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - public Builder update() { - return new Builder(this); - } - - public static Builder create() { - return new Builder(new NodeInstanceEventBody()); - } - - public static class Builder { - - private NodeInstanceEventBody instance; - - private Builder(NodeInstanceEventBody instance) { - this.instance = instance; - } - - public Builder id(String id) { - instance.id = id; - return this; - } - - public Builder nodeId(String nodeId) { - instance.nodeId = nodeId; - return this; - } - - public Builder nodeDefinitionId(String nodeDefinitionId) { - instance.nodeDefinitionId = nodeDefinitionId; - return this; - } - - public Builder nodeName(String nodeName) { - instance.nodeName = nodeName; - return this; - } - - public Builder nodeType(String nodeType) { - instance.nodeType = nodeType; - return this; - } - - public Builder triggerTime(Date triggerTime) { - instance.triggerTime = triggerTime; - return this; - } - - public Builder leaveTime(Date leaveTime) { - instance.leaveTime = leaveTime; - return this; - } - - public NodeInstanceEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessDefinitionEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessDefinitionEventBody.java new file mode 100644 index 00000000000..9a6a61813de --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessDefinitionEventBody.java @@ -0,0 +1,188 @@ +/* + * 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.event.process; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public class ProcessDefinitionEventBody { + private String id; + private String name; + private String description; + private String version; + private String type; + private Set roles; + private Set addons; + private Set annotations; + private String endpoint; + private String source; + private Map metadata; + private Collection nodes; + + public ProcessDefinitionEventBody() { + } + + public ProcessDefinitionEventBody(String id, String name, String description, String version, String type, Set roles, Set addons, Set annotations, String endpoint, + String source, Map metadata, Collection nodes) { + this.id = id; + this.name = name; + this.description = description; + this.version = version; + this.type = type; + this.roles = roles; + this.addons = addons; + this.annotations = annotations; + this.endpoint = endpoint; + this.source = source; + this.metadata = metadata; + this.nodes = nodes; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + + public String getType() { + return type; + } + + public Set getRoles() { + return roles; + } + + public Set getAddons() { + return addons; + } + + public String getEndpoint() { + return endpoint; + } + + public String getSource() { + return source; + } + + public Collection getNodes() { + return nodes; + } + + public String getDescription() { + return description; + } + + public Set getAnnotations() { + return annotations; + } + + public Map getMetadata() { + return metadata; + } + + public static ProcessDefinitionEventBodyBuilder builder() { + return new ProcessDefinitionEventBodyBuilder(); + } + + public static class ProcessDefinitionEventBodyBuilder { + private String id; + private String name; + private String description; + private String version; + private String type; + private Set roles; + private Set addons; + private Set annotations; + private String endpoint; + private String source; + private Map metadata; + private Collection nodes; + + public ProcessDefinitionEventBodyBuilder setId(String id) { + this.id = id; + return this; + } + + public ProcessDefinitionEventBodyBuilder setName(String name) { + this.name = name; + return this; + } + + public ProcessDefinitionEventBodyBuilder setVersion(String version) { + this.version = version; + return this; + } + + public ProcessDefinitionEventBodyBuilder setType(String type) { + this.type = type; + return this; + } + + public ProcessDefinitionEventBodyBuilder setRoles(Set roles) { + this.roles = roles; + return this; + } + + public ProcessDefinitionEventBodyBuilder setAddons(Set addons) { + this.addons = addons; + return this; + } + + public ProcessDefinitionEventBodyBuilder setEndpoint(String endpoint) { + this.endpoint = endpoint; + return this; + } + + public ProcessDefinitionEventBodyBuilder setSource(String source) { + this.source = source; + return this; + } + + public ProcessDefinitionEventBodyBuilder setDescription(String description) { + this.description = description; + return this; + } + + public ProcessDefinitionEventBodyBuilder setAnnotations(Set annotations) { + this.annotations = annotations; + return this; + } + + public ProcessDefinitionEventBodyBuilder setMetadata(Map metadata) { + this.metadata = metadata; + return this; + } + + public ProcessDefinitionEventBodyBuilder setNodes(Collection nodes) { + this.nodes = nodes; + return this; + } + + public ProcessDefinitionEventBody build() { + return new ProcessDefinitionEventBody(id, name, description, version, type, roles, addons, annotations, endpoint, source, metadata, nodes); + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessErrorEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessErrorEventBody.java deleted file mode 100644 index 6ddf32a57f9..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessErrorEventBody.java +++ /dev/null @@ -1,68 +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.event.process; - -public class ProcessErrorEventBody { - - private String nodeDefinitionId; - private String errorMessage; - - private ProcessErrorEventBody() { - } - - public String getNodeDefinitionId() { - return nodeDefinitionId; - } - - public String getErrorMessage() { - return errorMessage; - } - - @Override - public String toString() { - return "ProcessError [nodeDefinitionId=" + nodeDefinitionId + ", errorMessage=" + errorMessage + "]"; - } - - public static Builder create() { - return new Builder(new ProcessErrorEventBody()); - } - - public static class Builder { - - private ProcessErrorEventBody instance; - - private Builder(ProcessErrorEventBody instance) { - this.instance = instance; - } - - public Builder nodeDefinitionId(String nodeDefinitionId) { - instance.nodeDefinitionId = nodeDefinitionId; - return this; - } - - public Builder errorMessage(String errorMessage) { - instance.errorMessage = errorMessage; - return this; - } - - public ProcessErrorEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceErrorEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceErrorEventBody.java new file mode 100644 index 00000000000..a6ea8e77855 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceErrorEventBody.java @@ -0,0 +1,141 @@ +/* + * 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.event.process; + +import java.util.Date; + +public class ProcessInstanceErrorEventBody { + + // common fields for events + private Date eventDate; + + private String eventUser; + + // data fields for process instance event + + private String processId; + + private String processVersion; + + private String processInstanceId; + + // customs data fields for this event + + private String nodeDefinitionId; + + private String nodeInstanceId; + + private String errorMessage; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getProcessId() { + return processId; + } + + public String getProcessVersion() { + return processVersion; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public String getNodeDefinitionId() { + return nodeDefinitionId; + } + + public String getNodeInstanceId() { + return nodeInstanceId; + } + + public String getErrorMessage() { + return errorMessage; + } + + @Override + public String toString() { + return "ProcessErrorEventBody [processId=" + processId + ", processInstanceId=" + processInstanceId + ", nodeDefinitionId=" + nodeDefinitionId + ", nodeInstanceId=" + nodeInstanceId + + ", errorMessage=" + errorMessage + "]"; + } + + public static Builder create() { + return new Builder(new ProcessInstanceErrorEventBody()); + } + + public static class Builder { + + private ProcessInstanceErrorEventBody instance; + + private Builder(ProcessInstanceErrorEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder processId(String processId) { + this.instance.processId = processId; + return this; + } + + public Builder processVersion(String version) { + this.instance.processVersion = version; + return this; + } + + public Builder processInstanceId(String processInstanceId) { + this.instance.processInstanceId = processInstanceId; + return this; + } + + public Builder nodeInstanceId(String nodeInstanceId) { + this.instance.nodeInstanceId = nodeInstanceId; + return this; + } + + public Builder nodeDefinitionId(String nodeDefinitionId) { + instance.nodeDefinitionId = nodeDefinitionId; + return this; + } + + public Builder errorMessage(String errorMessage) { + instance.errorMessage = errorMessage; + return this; + } + + public ProcessInstanceErrorEventBody build() { + return instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceEventBody.java deleted file mode 100644 index 044a6fbbdd6..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceEventBody.java +++ /dev/null @@ -1,313 +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.event.process; - -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -public class ProcessInstanceEventBody { - - public static final String ID_META_DATA = "kogito.processinstance.id"; - public static final String VERSION_META_DATA = "kogito.processinstance.version"; - public static final String PARENT_ID_META_DATA = "kogito.processinstance.parentInstanceId"; - public static final String ROOT_ID_META_DATA = "kogito.processinstance.rootInstanceId"; - public static final String PROCESS_ID_META_DATA = "kogito.processinstance.processId"; - public static final String PROCESS_TYPE_META_DATA = "kogito.processinstance.processType"; - public static final String ROOT_PROCESS_ID_META_DATA = "kogito.processinstance.rootProcessId"; - public static final String STATE_META_DATA = "kogito.processinstance.state"; - - private String id; - private String version; - private String parentInstanceId; - private String rootInstanceId; - private String processId; - private String processType; - private String rootProcessId; - private String processName; - private Date startDate; - private Date endDate; - - private Integer state; - - private String businessKey; - - private Set nodeInstances = new LinkedHashSet<>(); - - private Map variables; - - private ProcessErrorEventBody error; - - private Set roles; - - private Set milestones = Collections.emptySet(); - - private String identity; - - private ProcessInstanceEventBody() { - } - - public String getId() { - return id; - } - - public String getVersion() { - return version; - } - - public String getParentInstanceId() { - return parentInstanceId; - } - - public String getRootInstanceId() { - return rootInstanceId; - } - - public String getProcessId() { - return processId; - } - - public String getProcessType() { - return processType; - } - - public String getRootProcessId() { - return rootProcessId; - } - - public String getProcessName() { - return processName; - } - - public Date getStartDate() { - return startDate; - } - - public Date getEndDate() { - return endDate; - } - - public Integer getState() { - return state; - } - - public String getBusinessKey() { - return businessKey; - } - - public ProcessErrorEventBody getError() { - return error; - } - - public Set getNodeInstances() { - return nodeInstances; - } - - public Map getVariables() { - return variables; - } - - public Set getRoles() { - return roles; - } - - public Set getMilestones() { - return milestones; - } - - public String getIdentity() { - return identity; - } - - public Builder update() { - return new Builder(this); - } - - public Map metaData() { - Map metadata = new HashMap<>(); - metadata.put(ID_META_DATA, id); - metadata.put(VERSION_META_DATA, version); - metadata.put(PARENT_ID_META_DATA, parentInstanceId); - metadata.put(ROOT_ID_META_DATA, rootInstanceId); - metadata.put(PROCESS_ID_META_DATA, processId); - metadata.put(PROCESS_TYPE_META_DATA, processType); - metadata.put(ROOT_PROCESS_ID_META_DATA, rootProcessId); - metadata.put(STATE_META_DATA, String.valueOf(state)); - return metadata; - } - - @Override - public String toString() { - return "ProcessInstanceEventBody{" + - "id='" + id + '\'' + - ", version='" + version + '\'' + - ", parentInstanceId='" + parentInstanceId + '\'' + - ", rootInstanceId='" + rootInstanceId + '\'' + - ", processId='" + processId + '\'' + - ", processType='" + processType + '\'' + - ", rootProcessId='" + rootProcessId + '\'' + - ", processName='" + processName + '\'' + - ", startDate=" + startDate + - ", endDate=" + endDate + - ", state=" + state + - ", businessKey='" + businessKey + '\'' + - ", nodeInstances=" + nodeInstances + - ", variables=" + variables + - ", error=" + error + - ", roles=" + roles + - ", milestones=" + milestones + - ", identity=" + identity + - '}'; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ProcessInstanceEventBody other = (ProcessInstanceEventBody) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - public static Builder create() { - return new Builder(new ProcessInstanceEventBody()); - } - - public static class Builder { - - private ProcessInstanceEventBody instance; - - public Builder(ProcessInstanceEventBody instance) { - this.instance = instance; - } - - public Builder id(String id) { - instance.id = id; - return this; - } - - public Builder version(String version) { - instance.version = version; - return this; - } - - public Builder parentInstanceId(String parentInstanceId) { - instance.parentInstanceId = parentInstanceId; - return this; - } - - public Builder rootInstanceId(String rootInstanceId) { - instance.rootInstanceId = rootInstanceId; - return this; - } - - public Builder processId(String processId) { - instance.processId = processId; - return this; - } - - public Builder processType(String processType) { - instance.processType = processType; - return this; - } - - public Builder rootProcessId(String rootProcessId) { - instance.rootProcessId = rootProcessId; - return this; - } - - public Builder processName(String processName) { - instance.processName = processName; - return this; - } - - public Builder startDate(Date date) { - instance.startDate = date; - return this; - } - - public Builder endDate(Date date) { - instance.endDate = date; - return this; - } - - public Builder state(Integer state) { - instance.state = state; - return this; - } - - public Builder businessKey(String businessKey) { - instance.businessKey = businessKey; - return this; - } - - public Builder identity(String identity) { - instance.identity = identity; - return this; - } - - public Builder nodeInstance(NodeInstanceEventBody nodeInstance) { - instance.nodeInstances.add(nodeInstance); - return this; - } - - public Builder variables(Map variables) { - instance.variables = variables; - return this; - } - - public Builder error(ProcessErrorEventBody error) { - instance.error = error; - return this; - } - - public Builder roles(String... roles) { - instance.roles = Set.of(roles); - return this; - } - - public Builder milestones(Set milestones) { - instance.milestones = milestones; - return this; - } - - public ProcessInstanceEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceEventMetadata.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceEventMetadata.java new file mode 100644 index 00000000000..c0acb7750f6 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceEventMetadata.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.event.process; + +public final class ProcessInstanceEventMetadata { + + public static final String PROCESS_ID_META_DATA = "kogito.process.id"; + public static final String PROCESS_TYPE_META_DATA = "kogito.process.type"; + public static final String PROCESS_VERSION_META_DATA = "kogito.process.version"; + + public static final String PROCESS_INSTANCE_ID_META_DATA = "kogito.processinstance.id"; + public static final String PROCESS_INSTANCE_STATE_META_DATA = "kogito.processinstance.state"; + public static final String PARENT_PROCESS_INSTANCE_ID_META_DATA = "kogito.processinstance.parentInstanceId"; + + public static final String ROOT_PROCESS_INSTANCE_ID_META_DATA = "kogito.processinstance.rootInstanceId"; + public static final String ROOT_PROCESS_ID_META_DATA = "kogito.processinstance.rootProcessId"; + + private ProcessInstanceEventMetadata() { + // nothing to comment + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceNodeEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceNodeEventBody.java new file mode 100644 index 00000000000..704f9be1ac4 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceNodeEventBody.java @@ -0,0 +1,218 @@ +/* + * 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.event.process; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class ProcessInstanceNodeEventBody { + + public static final int EVENT_TYPE_ENTER = 1; + + public static final int EVENT_TYPE_EXIT = 2; + + // common fields for events + + private Date eventDate; + + private String eventUser; + + private Integer eventType; // enter, leave, obsolete.... + + // data fields for process instance event + + private String processId; + + private String processVersion; + + private String processInstanceId; + + // custom data fields + + private String connectionNodeInstanceId; // only for entering and leaving + + private String nodeDefinitionId; // definition on bpmn2 + + private String nodeName; // evaluated name + + private String nodeType; + + private String nodeInstanceId; + + private Map data; + + private ProcessInstanceNodeEventBody() { + this.data = new HashMap<>(); + } + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public Integer getEventType() { + return eventType; + } + + public String getProcessId() { + return processId; + } + + public String getProcessVersion() { + return processVersion; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public String getConnectionNodeInstanceId() { + return connectionNodeInstanceId; + } + + public String getNodeDefinitionId() { + return nodeDefinitionId; + } + + public String getNodeName() { + return nodeName; + } + + public String getNodeType() { + return nodeType; + } + + public String getNodeInstanceId() { + return nodeInstanceId; + } + + public Map getData() { + return data; + } + + @Override + public String toString() { + return "ProcessInstanceNodeEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", eventType=" + eventType + ", processId=" + processId + ", processVersion=" + processVersion + + ", processInstanceId=" + processInstanceId + ", connectionNodeInstanceId=" + connectionNodeInstanceId + ", nodeDefinitionId=" + nodeDefinitionId + ", nodeName=" + nodeName + + ", nodeType=" + nodeType + ", nodeInstanceId=" + nodeInstanceId + ", data=" + data + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(nodeInstanceId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ProcessInstanceNodeEventBody other = (ProcessInstanceNodeEventBody) obj; + return Objects.equals(nodeInstanceId, other.nodeInstanceId); + } + + public Builder update() { + return new Builder(this); + } + + public static Builder create() { + return new Builder(new ProcessInstanceNodeEventBody()); + } + + public static class Builder { + + private ProcessInstanceNodeEventBody instance; + + private Builder(ProcessInstanceNodeEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder eventType(Integer eventType) { + this.instance.eventType = eventType; + return this; + } + + public Builder processId(String processId) { + this.instance.processId = processId; + return this; + } + + public Builder processVersion(String processVersion) { + this.instance.processVersion = processVersion; + return this; + } + + public Builder processInstanceId(String processInstanceId) { + instance.processInstanceId = processInstanceId; + return this; + } + + public Builder connectionNodeInstanceId(String connectionNodeInstanceId) { + instance.connectionNodeInstanceId = connectionNodeInstanceId; + return this; + } + + public Builder nodeDefinitionId(String nodeDefinitionId) { + instance.nodeDefinitionId = nodeDefinitionId; + return this; + } + + public Builder nodeName(String nodeName) { + instance.nodeName = nodeName; + return this; + } + + public Builder nodeType(String nodeType) { + instance.nodeType = nodeType; + return this; + } + + public Builder nodeInstanceId(String nodeInstanceId) { + this.instance.nodeInstanceId = nodeInstanceId; + return this; + } + + public Builder data(String name, Object value) { + instance.data.put(name, value); + return this; + } + + public ProcessInstanceNodeEventBody build() { + return instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceSLAEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceSLAEventBody.java new file mode 100644 index 00000000000..91fc9f75ec8 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceSLAEventBody.java @@ -0,0 +1,128 @@ +/* + * 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.event.process; + +import java.util.Date; + +public class ProcessInstanceSLAEventBody { + + // common fields for events + private Date eventDate; + + private String eventUser; + + // data fields for process instance event + + private String processId; + + private String processVersion; + + private String processInstanceId; + + // customs data fields for this event + + private String nodeDefinitionId; + + private String nodeInstanceId; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getProcessId() { + return processId; + } + + public String getProcessVersion() { + return processVersion; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public String getNodeDefinitionId() { + return nodeDefinitionId; + } + + public String getNodeInstanceId() { + return nodeInstanceId; + } + + @Override + public String toString() { + return "ProcessErrorEventBody [processId=" + processId + ", processInstanceId=" + processInstanceId + ", nodeDefinitionId=" + nodeDefinitionId + ", nodeInstanceId=" + nodeInstanceId + "]"; + } + + public static Builder create() { + return new Builder(new ProcessInstanceSLAEventBody()); + } + + public static class Builder { + + private ProcessInstanceSLAEventBody instance; + + private Builder(ProcessInstanceSLAEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder processId(String processId) { + this.instance.processId = processId; + return this; + } + + public Builder processVersion(String version) { + this.instance.processVersion = version; + return this; + } + + public Builder processInstanceId(String processInstanceId) { + this.instance.processInstanceId = processInstanceId; + return this; + } + + public Builder nodeInstanceId(String nodeInstanceId) { + this.instance.nodeInstanceId = nodeInstanceId; + return this; + } + + public Builder nodeDefinitionId(String nodeDefinitionId) { + instance.nodeDefinitionId = nodeDefinitionId; + return this; + } + + public ProcessInstanceSLAEventBody build() { + return instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceStateEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceStateEventBody.java new file mode 100644 index 00000000000..a6cc39229b9 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceStateEventBody.java @@ -0,0 +1,252 @@ +/* + * 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.event.process; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +public class ProcessInstanceStateEventBody { + + public static final int EVENT_TYPE_STARTED = 1; + public static final int EVENT_TYPE_ENDED = 2; + + // common fields for events + private Date eventDate; + + private String eventUser; + + private Integer eventType; // start, complete, error.... + + // data fields for process instance event + + private String processId; + + private String processVersion; + + private String processType; + + private String processInstanceId; + + // custom data fields + + private String businessKey; + + private String processName; + + private String parentInstanceId; + + private String rootProcessId; + + private String rootProcessInstanceId; + + private Integer state; + + private Set roles; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public Integer getEventType() { + return eventType; + } + + public String getProcessId() { + return processId; + } + + public String getProcessVersion() { + return processVersion; + } + + public String getProcessType() { + return processType; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public String getProcessName() { + return processName; + } + + public String getBusinessKey() { + return businessKey; + } + + public String getParentInstanceId() { + return parentInstanceId; + } + + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + public String getRootProcessId() { + return rootProcessId; + } + + public Integer getState() { + return state; + } + + public Set getRoles() { + return roles; + } + + public Builder update() { + return new Builder(this); + } + + public Map metaData() { + Map metadata = new HashMap<>(); + metadata.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, processInstanceId); + metadata.put(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA, processVersion); + metadata.put(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA, parentInstanceId); + metadata.put(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA, rootProcessInstanceId); + metadata.put(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA, processId); + metadata.put(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA, processType); + metadata.put(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA, rootProcessId); + metadata.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA, String.valueOf(state)); + return metadata; + } + + @Override + public String toString() { + return "ProcessInstanceStateEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", eventType=" + eventType + ", processId=" + processId + ", processVersion=" + processVersion + + ", processType=" + processType + ", processInstanceId=" + processInstanceId + ", businessKey=" + businessKey + ", processName=" + processName + ", parentInstanceId=" + + parentInstanceId + ", rootProcessId=" + rootProcessId + ", rootProcessInstanceId=" + rootProcessInstanceId + ", state=" + state + ", roles=" + roles + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(processInstanceId); + } + + public void setProcessInstanceId(String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ProcessInstanceStateEventBody other = (ProcessInstanceStateEventBody) obj; + return Objects.equals(processInstanceId, other.processInstanceId); + } + + public static Builder create() { + return new Builder(new ProcessInstanceStateEventBody()); + } + + public static class Builder { + + private ProcessInstanceStateEventBody instance; + + public Builder(ProcessInstanceStateEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder eventType(Integer eventType) { + this.instance.eventType = eventType; + return this; + } + + public Builder processId(String processId) { + this.instance.processId = processId; + return this; + } + + public Builder processVersion(String processVersion) { + this.instance.processVersion = processVersion; + return this; + } + + public Builder processType(String processType) { + this.instance.processType = processType; + return this; + } + + public Builder processInstanceId(String processInstanceId) { + this.instance.processInstanceId = processInstanceId; + return this; + } + + public Builder businessKey(String businessKey) { + this.instance.businessKey = businessKey; + return this; + } + + public Builder processName(String processName) { + this.instance.processName = processName; + return this; + } + + public Builder parentInstanceId(String parentInstanceId) { + this.instance.parentInstanceId = parentInstanceId; + return this; + } + + public Builder rootProcessId(String rootProcessId) { + this.instance.rootProcessId = rootProcessId; + return this; + } + + public Builder rootProcessInstanceId(String rootProcessInstanceId) { + this.instance.rootProcessInstanceId = rootProcessInstanceId; + return this; + } + + public Builder state(Integer state) { + this.instance.state = state; + return this; + } + + public Builder roles(String... roles) { + instance.roles = Set.of(roles); + return this; + } + + public ProcessInstanceStateEventBody build() { + return instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceVariableEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceVariableEventBody.java new file mode 100644 index 00000000000..00a55b9cd86 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/ProcessInstanceVariableEventBody.java @@ -0,0 +1,187 @@ +/* + * 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.event.process; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class ProcessInstanceVariableEventBody { + + // common fields for events + private Date eventDate; + + private String eventUser; + + // data fields for process instance event + + private String processId; + + private String processVersion; + + private String processInstanceId; + + // custom data fields for this event + private String nodeContainerDefinitionId; + private String nodeContainerInstanceId; + + private String variableId; + private String variableName; + private Object variableValue; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getProcessId() { + return processId; + } + + public String getProcessVersion() { + return processVersion; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public String getNodeContainerDefinitionId() { + return nodeContainerDefinitionId; + } + + public String getNodeContainerInstanceId() { + return nodeContainerInstanceId; + } + + public String getVariableId() { + return variableId; + } + + public String getVariableName() { + return variableName; + } + + public Object getVariableValue() { + return variableValue; + } + + public Map metaData() { + Map metadata = new HashMap<>(); + metadata.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, processInstanceId); + metadata.put(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA, processId); + return metadata; + } + + @Override + public String toString() { + return "ProcessInstanceVariableEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", processId=" + processId + ", processVersion=" + processVersion + + ", processInstanceId=" + processInstanceId + ", nodeContainerDefinitionId=" + nodeContainerDefinitionId + ", nodeContainerInstanceId=" + + nodeContainerInstanceId + ", variableId=" + variableId + + ", variableName=" + variableName + ", variableValue=" + variableValue + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(nodeContainerInstanceId, processInstanceId, variableId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ProcessInstanceVariableEventBody other = (ProcessInstanceVariableEventBody) obj; + return Objects.equals(nodeContainerInstanceId, other.nodeContainerInstanceId) && Objects.equals(processInstanceId, other.processInstanceId) && Objects.equals(variableId, other.variableId); + } + + public static Builder create() { + return new Builder(new ProcessInstanceVariableEventBody()); + } + + public static class Builder { + + private ProcessInstanceVariableEventBody instance; + + public Builder(ProcessInstanceVariableEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder processId(String processId) { + this.instance.processId = processId; + return this; + } + + public Builder processVersion(String processVersion) { + this.instance.processVersion = processVersion; + return this; + } + + public Builder processInstanceId(String processInstanceId) { + this.instance.processInstanceId = processInstanceId; + return this; + } + + public Builder nodeContainerDefinitionId(String nodeContainerDefinitionId) { + this.instance.nodeContainerDefinitionId = nodeContainerDefinitionId; + return this; + } + + public Builder nodeContainerInstanceId(String nodeContainerInstanceId) { + this.instance.nodeContainerInstanceId = nodeContainerInstanceId; + return this; + } + + public Builder variableId(String variableId) { + this.instance.variableId = variableId; + return this; + } + + public Builder variableName(String variableName) { + this.instance.variableName = variableName; + return this; + } + + public Builder variableValue(Object variableValue) { + this.instance.variableValue = variableValue; + return this; + } + + public ProcessInstanceVariableEventBody build() { + return instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/UserTaskDeadlineEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/UserTaskDeadlineEventBody.java deleted file mode 100644 index 34cfaa56d3f..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/UserTaskDeadlineEventBody.java +++ /dev/null @@ -1,245 +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.event.process; - -import java.util.Collection; -import java.util.Date; -import java.util.Map; -import java.util.Set; - -public class UserTaskDeadlineEventBody { - - private Map notification; - private String id; - private String taskName; - private String taskDescription; - private String taskPriority; - private String referenceName; - private Date startDate; - private String state; - private String actualOwner; - private Set potentialUsers; - private Set potentialGroups; - - private Map inputs; - private Map outputs; - private String processInstanceId; - private String rootProcessInstanceId; - private String processId; - private String rootProcessId; - private Collection comments; - private Collection attachments; - - public UserTaskDeadlineEventBody() { - } - - private UserTaskDeadlineEventBody(String id, Map notification) { - this.id = id; - this.notification = notification; - } - - public String getId() { - return id; - } - - public String getTaskName() { - return taskName; - } - - public String getTaskDescription() { - return taskDescription; - } - - public String getTaskPriority() { - return taskPriority; - } - - public String getReferenceName() { - return referenceName; - } - - public Date getStartDate() { - return startDate; - } - - public String getState() { - return state; - } - - public String getActualOwner() { - return actualOwner; - } - - public Map getInputs() { - return inputs; - } - - public Map getOutputs() { - return outputs; - } - - public String getProcessInstanceId() { - return processInstanceId; - } - - public String getRootProcessInstanceId() { - return rootProcessInstanceId; - } - - public String getProcessId() { - return processId; - } - - public String getRootProcessId() { - return rootProcessId; - } - - public static Builder create(String id, Map notification) { - return new Builder(new UserTaskDeadlineEventBody(id, notification)); - } - - public Map getNotification() { - return notification; - } - - public Set getPotentialUsers() { - return potentialUsers; - } - - public Set getPotentialGroups() { - return potentialGroups; - } - - public Collection getComments() { - return comments; - } - - public Collection getAttachments() { - return attachments; - } - - public static class Builder { - - private UserTaskDeadlineEventBody instance; - - protected Builder(UserTaskDeadlineEventBody instance) { - this.instance = instance; - } - - public Builder taskName(String taskName) { - instance.taskName = taskName; - return this; - } - - public Builder taskDescription(String taskDescription) { - instance.taskDescription = taskDescription; - return this; - } - - public Builder taskPriority(String taskPriority) { - instance.taskPriority = taskPriority; - return this; - } - - public Builder referenceName(String referenceName) { - instance.referenceName = referenceName; - return this; - } - - public Builder state(String state) { - instance.state = state; - return this; - } - - public Builder actualOwner(String actualOwner) { - instance.actualOwner = actualOwner; - return this; - } - - public Builder startDate(Date startDate) { - instance.startDate = startDate; - return this; - } - - public Builder inputs(Map inputs) { - instance.inputs = inputs; - return this; - } - - public Builder outputs(Map outputs) { - instance.outputs = outputs; - return this; - } - - public Builder processInstanceId(String processInstanceId) { - instance.processInstanceId = processInstanceId; - return this; - } - - public Builder rootProcessInstanceId(String rootProcessInstanceId) { - instance.rootProcessInstanceId = rootProcessInstanceId; - return this; - } - - public Builder processId(String processId) { - instance.processId = processId; - return this; - } - - public Builder rootProcessId(String rootProcessId) { - instance.rootProcessId = rootProcessId; - return this; - } - - public Builder potentialUsers(Set potentialUsers) { - instance.potentialUsers = potentialUsers; - return this; - } - - public Builder potentialGroups(Set potentialGroups) { - instance.potentialGroups = potentialGroups; - return this; - } - - public Builder comments(Collection comments) { - instance.comments = comments; - return this; - } - - public Builder attachments(Collection attachments) { - instance.attachments = attachments; - return this; - } - - public UserTaskDeadlineEventBody build() { - return instance; - } - } - - @Override - public String toString() { - return "UserTaskDeadlineEventBody [notification=" + notification + ", id=" + id + ", taskName=" + taskName + - ", taskDescription=" + taskDescription + ", taskPriority=" + taskPriority + ", referenceName=" + - referenceName + ", startDate=" + startDate + ", state=" + state + ", actualOwner=" + actualOwner + - ", potentialUsers=" + potentialUsers + ", potentialGroups=" + potentialGroups + ", inputs=" + inputs + - ", outputs=" + outputs + ", processInstanceId=" + processInstanceId + ", rootProcessInstanceId=" + - rootProcessInstanceId + ", processId=" + processId + ", rootProcessId=" + rootProcessId + - ", comments=" + comments + ", attachments=" + attachments + "]"; - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/UserTaskInstanceEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/UserTaskInstanceEventBody.java deleted file mode 100644 index 976ccc63804..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/UserTaskInstanceEventBody.java +++ /dev/null @@ -1,378 +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.event.process; - -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class UserTaskInstanceEventBody { - - public static final String UT_ID_META_DATA = "kogito.usertaskinstance.id"; - public static final String UT_STATE_META_DATA = "kogito.usertaskinstance.state"; - - private String id; - private String taskName; - private String taskDescription; - private String taskPriority; - private String referenceName; - private Date startDate; - private Date completeDate; - - private String state; - - private String actualOwner; - private Set potentialUsers; - private Set potentialGroups; - private Set excludedUsers; - private Set adminUsers; - private Set adminGroups; - - private Map inputs; - private Map outputs; - - private Collection comments; - private Collection attachments; - - private String processInstanceId; - private String processInstanceVersion; - private String rootProcessInstanceId; - private String processId; - private String rootProcessId; - - private String identity; - - private UserTaskInstanceEventBody() { - - } - - public String getId() { - return id; - } - - public String getTaskName() { - return taskName; - } - - public String getTaskDescription() { - return taskDescription; - } - - public String getTaskPriority() { - return taskPriority; - } - - public String getReferenceName() { - return referenceName; - } - - public Date getStartDate() { - return startDate; - } - - public Date getCompleteDate() { - return completeDate; - } - - public String getState() { - return state; - } - - public String getActualOwner() { - return actualOwner; - } - - public Set getPotentialUsers() { - return potentialUsers; - } - - public Set getPotentialGroups() { - return potentialGroups; - } - - public Set getExcludedUsers() { - return excludedUsers; - } - - public Set getAdminUsers() { - return adminUsers; - } - - public Set getAdminGroups() { - return adminGroups; - } - - public Map getInputs() { - return inputs; - } - - public Map getOutputs() { - return outputs; - } - - public String getProcessInstanceId() { - return processInstanceId; - } - - public String getProcessInstanceVersion() { - return processInstanceVersion; - } - - public String getRootProcessInstanceId() { - return rootProcessInstanceId; - } - - public String getProcessId() { - return processId; - } - - public String getRootProcessId() { - return rootProcessId; - } - - public Collection getComments() { - return comments; - } - - public void setComments(Collection comments) { - this.comments = comments; - } - - public Collection getAttachments() { - return attachments; - } - - public void setAttachments(Collection attachments) { - this.attachments = attachments; - } - - public String getIdentity() { - return identity; - } - - public Map metaData() { - Map metadata = new HashMap<>(); - metadata.put(UT_ID_META_DATA, id); - metadata.put(ProcessInstanceEventBody.ID_META_DATA, processInstanceId); - metadata.put(ProcessInstanceEventBody.VERSION_META_DATA, processInstanceVersion); - metadata.put(ProcessInstanceEventBody.ROOT_ID_META_DATA, rootProcessInstanceId); - metadata.put(ProcessInstanceEventBody.PROCESS_ID_META_DATA, processId); - metadata.put(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA, rootProcessId); - metadata.put(UT_STATE_META_DATA, state); - return metadata; - } - - @Override - public String toString() { - return "UserTaskInstanceEventBody{" + - "id='" + id + '\'' + - ", taskName='" + taskName + '\'' + - ", taskDescription='" + taskDescription + '\'' + - ", taskPriority='" + taskPriority + '\'' + - ", referenceName='" + referenceName + '\'' + - ", startDate=" + startDate + - ", completeDate=" + completeDate + - ", state='" + state + '\'' + - ", actualOwner='" + actualOwner + '\'' + - ", potentialUsers=" + potentialUsers + - ", potentialGroups=" + potentialGroups + - ", excludedUsers=" + excludedUsers + - ", adminUsers=" + adminUsers + - ", adminGroups=" + adminGroups + - ", inputs=" + inputs + - ", outputs=" + outputs + - ", comments=" + comments + - ", attachments=" + attachments + - ", processInstanceId='" + processInstanceId + '\'' + - ", processInstanceVersion='" + processInstanceVersion + '\'' + - ", rootProcessInstanceId='" + rootProcessInstanceId + '\'' + - ", processId='" + processId + '\'' + - ", rootProcessId='" + rootProcessId + '\'' + - ", identity='" + identity + '\'' + - '}'; - } - - public Builder update() { - return new Builder(this); - } - - public static Builder create() { - return new Builder(new UserTaskInstanceEventBody()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - UserTaskInstanceEventBody other = (UserTaskInstanceEventBody) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - return true; - } - - public static class Builder { - - private UserTaskInstanceEventBody instance; - - private Builder(UserTaskInstanceEventBody instance) { - this.instance = instance; - } - - public Builder id(String id) { - instance.id = id; - return this; - } - - public Builder taskName(String taskName) { - instance.taskName = taskName; - return this; - } - - public Builder taskDescription(String taskDescription) { - instance.taskDescription = taskDescription; - return this; - } - - public Builder taskPriority(String taskPriority) { - instance.taskPriority = taskPriority; - return this; - } - - public Builder referenceName(String referenceName) { - instance.referenceName = referenceName; - return this; - } - - public Builder state(String state) { - instance.state = state; - return this; - } - - public Builder actualOwner(String actualOwner) { - instance.actualOwner = actualOwner; - return this; - } - - public UserTaskInstanceEventBody build() { - return instance; - } - - public Builder startDate(Date startDate) { - instance.startDate = startDate; - return this; - } - - public Builder completeDate(Date completeDate) { - instance.completeDate = completeDate; - return this; - } - - public Builder potentialUsers(Set potentialUsers) { - instance.potentialUsers = potentialUsers; - return this; - } - - public Builder potentialGroups(Set potentialGroups) { - instance.potentialGroups = potentialGroups; - return this; - } - - public Builder excludedUsers(Set excludedUsers) { - instance.excludedUsers = excludedUsers; - return this; - } - - public Builder adminUsers(Set adminUsers) { - instance.adminUsers = adminUsers; - return this; - } - - public Builder adminGroups(Set adminGroups) { - instance.adminGroups = adminGroups; - return this; - } - - public Builder inputs(Map inputs) { - instance.inputs = inputs; - return this; - } - - public Builder outputs(Map outputs) { - instance.outputs = outputs; - return this; - } - - public Builder comments(Collection comments) { - instance.comments = comments; - return this; - } - - public Builder attachments(Collection attachments) { - instance.attachments = attachments; - return this; - } - - public Builder processInstanceId(String processInstanceId) { - instance.processInstanceId = processInstanceId; - return this; - } - - public Builder processInstanceVersion(String processInstanceVersion) { - instance.processInstanceVersion = processInstanceVersion; - return this; - } - - public Builder rootProcessInstanceId(String rootProcessInstanceId) { - instance.rootProcessInstanceId = rootProcessInstanceId; - return this; - } - - public Builder processId(String processId) { - instance.processId = processId; - return this; - } - - public Builder rootProcessId(String rootProcessId) { - instance.rootProcessId = rootProcessId; - return this; - } - - public Builder identity(String identity) { - instance.identity = identity; - return this; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/VariableInstanceEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/VariableInstanceEventBody.java deleted file mode 100644 index 7cd46b7d0b2..00000000000 --- a/api/kogito-events-api/src/main/java/org/kie/kogito/event/process/VariableInstanceEventBody.java +++ /dev/null @@ -1,264 +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.event.process; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -public class VariableInstanceEventBody { - - public static final String ID_META_DATA = "kogito.processinstance.id"; - public static final String PARENT_ID_META_DATA = "kogito.processinstance.parentInstanceId"; - public static final String ROOT_ID_META_DATA = "kogito.processinstance.rootInstanceId"; - public static final String PROCESS_ID_META_DATA = "kogito.processinstance.processId"; - public static final String ROOT_PROCESS_ID_META_DATA = "kogito.processinstance.rootProcessId"; - public static final String STATE_META_DATA = "kogito.processinstance.state"; - - private String variableName; - private Object variableValue; - private Object variablePreviousValue; - private Date changeDate; - - private String changedByNodeId; - private String changedByNodeName; - private String changedByNodeType; - private String processInstanceId; - private String rootProcessInstanceId; - private String processId; - private String rootProcessId; - - private String identity; - - private VariableInstanceEventBody() { - } - - public String getVariableName() { - return variableName; - } - - public Object getVariableValue() { - return variableValue; - } - - public Object getVariablePreviousValue() { - return variablePreviousValue; - } - - public Date getChangeDate() { - return changeDate; - } - - public String getChangedByNodeId() { - return changedByNodeId; - } - - public String getChangedByNodeName() { - return changedByNodeName; - } - - public String getChangedByNodeType() { - return changedByNodeType; - } - - public String getProcessInstanceId() { - return processInstanceId; - } - - public String getRootProcessInstanceId() { - return rootProcessInstanceId; - } - - public String getProcessId() { - return processId; - } - - public String getRootProcessId() { - return rootProcessId; - } - - public String getIdentity() { - return identity; - } - - public Map metaData() { - Map metadata = new HashMap<>(); - metadata.put(ID_META_DATA, processInstanceId); - metadata.put(ROOT_ID_META_DATA, rootProcessInstanceId); - metadata.put(PROCESS_ID_META_DATA, processId); - metadata.put(ROOT_PROCESS_ID_META_DATA, rootProcessId); - return metadata; - } - - @Override - public String toString() { - return "VariableInstanceEventBody{" + - "variableName='" + variableName + '\'' + - ", variableValue=" + variableValue + - ", variablePreviousValue=" + variablePreviousValue + - ", changeDate=" + changeDate + - ", changedByNodeId='" + changedByNodeId + '\'' + - ", changedByNodeName='" + changedByNodeName + '\'' + - ", changedByNodeType='" + changedByNodeType + '\'' + - ", processInstanceId='" + processInstanceId + '\'' + - ", rootProcessInstanceId='" + rootProcessInstanceId + '\'' + - ", processId='" + processId + '\'' + - ", rootProcessId='" + rootProcessId + '\'' + - ", identity='" + identity + '\'' + - '}'; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((changedByNodeId == null) ? 0 : changedByNodeId.hashCode()); - result = prime * result + ((changedByNodeName == null) ? 0 : changedByNodeName.hashCode()); - result = prime * result + ((changedByNodeType == null) ? 0 : changedByNodeType.hashCode()); - result = prime * result + ((processInstanceId == null) ? 0 : processInstanceId.hashCode()); - result = prime * result + ((variableName == null) ? 0 : variableName.hashCode()); - result = prime * result + ((variablePreviousValue == null) ? 0 : variablePreviousValue.hashCode()); - result = prime * result + ((variableValue == null) ? 0 : variableValue.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - VariableInstanceEventBody other = (VariableInstanceEventBody) obj; - if (changedByNodeId == null) { - if (other.changedByNodeId != null) - return false; - } else if (!changedByNodeId.equals(other.changedByNodeId)) - return false; - if (changedByNodeName == null) { - if (other.changedByNodeName != null) - return false; - } else if (!changedByNodeName.equals(other.changedByNodeName)) - return false; - if (changedByNodeType == null) { - if (other.changedByNodeType != null) - return false; - } else if (!changedByNodeType.equals(other.changedByNodeType)) - return false; - if (processInstanceId == null) { - if (other.processInstanceId != null) - return false; - } else if (!processInstanceId.equals(other.processInstanceId)) - return false; - if (variableName == null) { - if (other.variableName != null) - return false; - } else if (!variableName.equals(other.variableName)) - return false; - if (variablePreviousValue == null) { - if (other.variablePreviousValue != null) - return false; - } else if (!variablePreviousValue.equals(other.variablePreviousValue)) - return false; - if (variableValue == null) { - if (other.variableValue != null) - return false; - } else if (!variableValue.equals(other.variableValue)) - return false; - return true; - } - - public static Builder create() { - return new Builder(new VariableInstanceEventBody()); - } - - public static class Builder { - - private VariableInstanceEventBody instance; - - public Builder(VariableInstanceEventBody instance) { - this.instance = instance; - } - - public Builder processInstanceId(String processInstanceId) { - instance.processInstanceId = processInstanceId; - return this; - } - - public Builder rootProcessInstanceId(String rootProcessInstanceId) { - instance.rootProcessInstanceId = rootProcessInstanceId; - return this; - } - - public Builder processId(String processId) { - instance.processId = processId; - return this; - } - - public Builder rootProcessId(String rootProcessId) { - instance.rootProcessId = rootProcessId; - return this; - } - - public Builder variableName(String variableName) { - instance.variableName = variableName; - return this; - } - - public Builder variableValue(Object variableValue) { - instance.variableValue = variableValue; - return this; - } - - public Builder variablePreviousValue(Object variablePreviousValue) { - instance.variablePreviousValue = variablePreviousValue; - return this; - } - - public Builder changeDate(Date changeDate) { - instance.changeDate = changeDate; - return this; - } - - public Builder changedByNodeId(String changedByNodeId) { - instance.changedByNodeId = changedByNodeId; - return this; - } - - public Builder changedByNodeName(String changedByNodeName) { - instance.changedByNodeName = changedByNodeName; - return this; - } - - public Builder changedByNodeType(String changedByNodeType) { - instance.changedByNodeType = changedByNodeType; - return this; - } - - public Builder identity(String identity) { - instance.identity = identity; - return this; - } - - public VariableInstanceEventBody build() { - return instance; - } - } -} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAssignmentEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAssignmentEventBody.java new file mode 100644 index 00000000000..69f0b74c8ea --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAssignmentEventBody.java @@ -0,0 +1,155 @@ +/* + * 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.event.usertask; + +import java.util.Date; +import java.util.List; +import java.util.Objects; + +public class UserTaskInstanceAssignmentEventBody { + + // common fields for events + private Date eventDate; + private String eventUser; + + private String userTaskDefinitionId; + private String userTaskInstanceId; + private String userTaskName; + + // custom data + private String assignmentType; // POT OWNERS, ADMIN... + + private List users; + + private String eventType; //ADDED REMOVED + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getUserTaskDefinitionId() { + return userTaskDefinitionId; + } + + public String getUserTaskInstanceId() { + return userTaskInstanceId; + } + + public String getUserTaskName() { + return userTaskName; + } + + public String getAssignmentType() { + return assignmentType; + } + + public List getUsers() { + return users; + } + + public String getEventType() { + return eventType; + } + + @Override + public String toString() { + return "UserTaskInstanceAssignmentEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", userTaskDefinitionId=" + userTaskDefinitionId + ", userTaskInstanceId=" + + userTaskInstanceId + ", userTaskName=" + userTaskName + ", assignmentType=" + assignmentType + ", users=" + users + ", eventType=" + eventType + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(assignmentType, userTaskInstanceId, users); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UserTaskInstanceAssignmentEventBody other = (UserTaskInstanceAssignmentEventBody) obj; + return Objects.equals(assignmentType, other.assignmentType) && Objects.equals(userTaskInstanceId, other.userTaskInstanceId) && Objects.equals(users, other.users); + } + + public static Builder create() { + return new Builder(new UserTaskInstanceAssignmentEventBody()); + } + + public static class Builder { + + private UserTaskInstanceAssignmentEventBody instance; + + private Builder(UserTaskInstanceAssignmentEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder userTaskDefinitionId(String userTaskDefinitionId) { + this.instance.userTaskDefinitionId = userTaskDefinitionId; + return this; + } + + public Builder userTaskInstanceId(String userTaskInstanceId) { + this.instance.userTaskInstanceId = userTaskInstanceId; + return this; + } + + public Builder userTaskName(String userTaskName) { + this.instance.userTaskName = userTaskName; + return this; + } + + public Builder assignmentType(String assignmentType) { + this.instance.assignmentType = assignmentType; + return this; + } + + public Builder users(String... usersId) { + this.instance.users = List.of(usersId); + return this; + } + + public Builder eventType(String eventType) { + this.instance.eventType = eventType; + return this; + } + + public UserTaskInstanceAssignmentEventBody build() { + return this.instance; + } + } + +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAttachmentEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAttachmentEventBody.java new file mode 100644 index 00000000000..9ae5c649f8f --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAttachmentEventBody.java @@ -0,0 +1,167 @@ +/* + * 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.event.usertask; + +import java.net.URI; +import java.util.Date; +import java.util.Objects; + +public class UserTaskInstanceAttachmentEventBody { + public static final int EVENT_TYPE_ADDED = 1; + public static final int EVENT_TYPE_CHANGE = 2; + public static final int EVENT_TYPE_DELETED = 3; + + // common fields for events + private Date eventDate; + private String eventUser; + + private String userTaskDefinitionId; + private String userTaskInstanceId; + private String userTaskName; + + // custome data fields + private String attachmentId; + private String attachmentName; + private URI attachmentURI; + + private int eventType; + + public static Builder create() { + return new Builder(new UserTaskInstanceAttachmentEventBody()); + } + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getUserTaskDefinitionId() { + return userTaskDefinitionId; + } + + public String getUserTaskInstanceId() { + return userTaskInstanceId; + } + + public String getUserTaskName() { + return userTaskName; + } + + public String getAttachmentId() { + return attachmentId; + } + + public String getAttachmentName() { + return attachmentName; + } + + public URI getAttachmentURI() { + return attachmentURI; + } + + public int getEventType() { + return eventType; + } + + @Override + public String toString() { + return "UserTaskInstanceAttachmentEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", userTaskDefinitionId=" + userTaskDefinitionId + ", userTaskInstanceId=" + + userTaskInstanceId + ", userTaskName=" + userTaskName + ", attachmentId=" + attachmentId + ", attachmentName=" + attachmentName + ", attachmentURI=" + attachmentURI + + ", eventType=" + eventType + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(attachmentId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UserTaskInstanceAttachmentEventBody other = (UserTaskInstanceAttachmentEventBody) obj; + return Objects.equals(attachmentId, other.attachmentId); + } + + public static class Builder { + + private UserTaskInstanceAttachmentEventBody instance; + + private Builder(UserTaskInstanceAttachmentEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder userTaskDefinitionId(String userTaskDefinitionId) { + this.instance.userTaskDefinitionId = userTaskDefinitionId; + return this; + } + + public Builder userTaskInstanceId(String userTaskInstanceId) { + this.instance.userTaskInstanceId = userTaskInstanceId; + return this; + } + + public Builder userTaskName(String userTaskName) { + this.instance.userTaskName = userTaskName; + return this; + } + + public Builder attachmentId(String attachmentId) { + this.instance.attachmentId = attachmentId; + return this; + } + + public Builder attachmentName(String attachmentName) { + this.instance.attachmentName = attachmentName; + return this; + } + + public Builder attachmentURI(URI attachmentURI) { + this.instance.attachmentURI = attachmentURI; + return this; + } + + public Builder eventType(int eventType) { + this.instance.eventType = eventType; + return this; + } + + public UserTaskInstanceAttachmentEventBody build() { + return this.instance; + } + } + +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceCommentEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceCommentEventBody.java new file mode 100644 index 00000000000..ca3e92e2bb4 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceCommentEventBody.java @@ -0,0 +1,162 @@ +/* + * 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.event.usertask; + +import java.util.Date; +import java.util.Objects; + +public class UserTaskInstanceCommentEventBody { + + public static final int EVENT_TYPE_ADDED = 1; + public static final int EVENT_TYPE_CHANGE = 2; + public static final int EVENT_TYPE_DELETED = 3; + + // common fields for events + private Date eventDate; + private String eventUser; + + private String userTaskDefinitionId; + private String userTaskInstanceId; + private String userTaskName; + + // custome data fields + private String commentId; + private String commentContent; + + private int eventType; + + private UserTaskInstanceCommentEventBody() { + } + + public static Builder create() { + return new Builder(new UserTaskInstanceCommentEventBody()); + } + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getUserTaskDefinitionId() { + return userTaskDefinitionId; + } + + public String getUserTaskInstanceId() { + return userTaskInstanceId; + } + + public String getUserTaskName() { + return userTaskName; + } + + public String getCommentId() { + return commentId; + } + + public String getCommentContent() { + return commentContent; + } + + public int getEventType() { + return eventType; + } + + @Override + public String toString() { + return "UserTaskInstanceCommentEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", userTaskDefinitionId=" + userTaskDefinitionId + ", userTaskInstanceId=" + userTaskInstanceId + + ", userTaskName=" + userTaskName + ", commentId=" + commentId + ", commentContent=" + commentContent + ", eventType=" + eventType + "]"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UserTaskInstanceCommentEventBody other = (UserTaskInstanceCommentEventBody) obj; + return Objects.equals(commentContent, other.commentContent) && Objects.equals(commentId, other.commentId) && Objects.equals(eventDate, other.eventDate); + } + + @Override + public int hashCode() { + return Objects.hash(commentContent, commentId, eventDate); + } + + public Builder update() { + return new Builder(this); + } + + public static class Builder { + + private UserTaskInstanceCommentEventBody instance; + + private Builder(UserTaskInstanceCommentEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String eventUser) { + this.instance.eventUser = eventUser; + return this; + } + + public Builder userTaskDefinitionId(String userTaskDefinitionId) { + this.instance.userTaskDefinitionId = userTaskDefinitionId; + return this; + } + + public Builder userTaskInstanceId(String userTaskInstanceId) { + this.instance.userTaskInstanceId = userTaskInstanceId; + return this; + } + + public Builder userTaskName(String userTaskName) { + this.instance.userTaskName = userTaskName; + return this; + } + + public Builder commentId(String commentId) { + this.instance.commentId = commentId; + return this; + } + + public Builder commentContent(String commentContent) { + this.instance.commentContent = commentContent; + return this; + } + + public Builder eventType(int eventType) { + this.instance.eventType = eventType; + return this; + } + + public UserTaskInstanceCommentEventBody build() { + return instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDeadlineEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDeadlineEventBody.java new file mode 100644 index 00000000000..97149d13a99 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDeadlineEventBody.java @@ -0,0 +1,137 @@ +/* + * 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.event.usertask; + +import java.util.Date; +import java.util.Map; + +public class UserTaskInstanceDeadlineEventBody { + + // common fields for events + private Date eventDate; + private String eventUser; + + private String userTaskDefinitionId; + private String userTaskInstanceId; + private String userTaskName; + + // custom data fields + + private Map notification; + + private Map inputs; + + private String eventType; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getUserTaskDefinitionId() { + return userTaskDefinitionId; + } + + public String getUserTaskInstanceId() { + return userTaskInstanceId; + } + + public String getUserTaskName() { + return userTaskName; + } + + public Map getNotification() { + return notification; + } + + public Map getInputs() { + return inputs; + } + + public String getEventType() { + return eventType; + } + + @Override + public String toString() { + return "UserTaskInstanceDeadlineEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", userTaskDefinitionId=" + userTaskDefinitionId + ", userTaskInstanceId=" + + userTaskInstanceId + ", userTaskName=" + userTaskName + ", notification=" + notification + ", inputs=" + inputs + ", eventType=" + eventType + "]"; + } + + public static Builder create() { + return new Builder(new UserTaskInstanceDeadlineEventBody()); + } + + public static class Builder { + + private UserTaskInstanceDeadlineEventBody instance; + + protected Builder(UserTaskInstanceDeadlineEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String eventUser) { + this.instance.eventUser = eventUser; + return this; + } + + public Builder userTaskDefinitionId(String userTaskDefinitionId) { + this.instance.userTaskDefinitionId = userTaskDefinitionId; + return this; + } + + public Builder userTaskInstanceId(String userTaskInstanceId) { + this.instance.userTaskInstanceId = userTaskInstanceId; + return this; + } + + public Builder userTaskName(String userTaskName) { + this.instance.userTaskName = userTaskName; + return this; + } + + public Builder notification(Map notification) { + this.instance.notification = notification; + return this; + } + + public Builder inputs(Map inputs) { + this.instance.inputs = inputs; + return this; + } + + public Builder eventType(String eventType) { + this.instance.eventType = eventType; + return this; + } + + public UserTaskInstanceDeadlineEventBody build() { + return instance; + } + } + +} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RuleUnitQueryJavaTemplate.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceEventMetadata.java similarity index 60% rename from kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RuleUnitQueryJavaTemplate.java rename to api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceEventMetadata.java index 0a681b9b43b..137b7e78053 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RuleUnitQueryJavaTemplate.java +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceEventMetadata.java @@ -16,22 +16,16 @@ * specific language governing permissions and limitations * under the License. */ -package com.myspace.demo; -import org.drools.ruleunits.api.RuleUnitInstance; +package org.kie.kogito.event.usertask; -import java.util.List; -import java.util.Map; +public final class UserTaskInstanceEventMetadata { -import static java.util.stream.Collectors.toList; + public static final String USER_TASK_INSTANCE_ID_META_DATA = "kogito.usertaskinstance.id"; + public static final String USER_TASK_INSTANCE_STATE_META_DATA = "kogito.usertaskinstance.state"; + public static final String USER_TASK_INSTANCE_REFERENCE_ID_META_DATA = "kogito.usertaskinstance.referenceId"; -public class $unit$Query$name$ { - - public static List<$ReturnType$> execute(RuleUnitInstance<$UnitType$> instance) { - return instance.executeQuery( "$queryName$" ).toList().stream().map($unit$Query$name$::toResult).collect(toList()); - } - - private static $ReturnType$ toResult(Map tuple) { - return ($ReturnType$) tuple.get(""); + private UserTaskInstanceEventMetadata() { + // nothing to comment } } diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceStateEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceStateEventBody.java new file mode 100644 index 00000000000..336f7fb4188 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceStateEventBody.java @@ -0,0 +1,212 @@ +/* + * 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.event.usertask; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceStateEventBody { + + // common fields for events + private Date eventDate; + private String eventUser; + + private String userTaskDefinitionId; + private String userTaskInstanceId; + private String userTaskName; + + // custom data fields + private Integer eventType; // CREATED, ADDED, CLAIMED.... + + private String userTaskDescription; + private String userTaskPriority; + private String userTaskReferenceName; + + private String state; + + private String actualOwner; + + private String processInstanceId; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getUserTaskDefinitionId() { + return userTaskDefinitionId; + } + + public String getUserTaskInstanceId() { + return userTaskInstanceId; + } + + public String getUserTaskName() { + return userTaskName; + } + + public Integer getEventType() { + return eventType; + } + + public String getUserTaskDescription() { + return userTaskDescription; + } + + public String getUserTaskPriority() { + return userTaskPriority; + } + + public String getUserTaskReferenceName() { + return userTaskReferenceName; + } + + public String getState() { + return state; + } + + public String getActualOwner() { + return actualOwner; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public Map metaData() { + Map metadata = new HashMap<>(); + metadata.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA, userTaskInstanceId); + metadata.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, processInstanceId); + metadata.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA, state); + return metadata; + } + + @Override + public String toString() { + return "UserTaskInstanceStateEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", userTaskDefinitionId=" + userTaskDefinitionId + ", userTaskInstanceId=" + userTaskInstanceId + + ", userTaskName=" + userTaskName + ", eventType=" + eventType + ", userTaskDescription=" + userTaskDescription + ", userTaskPriority=" + userTaskPriority + ", userTaskReferenceName=" + + userTaskReferenceName + + ", state=" + state + ", actualOwner=" + actualOwner + ", processInstanceId=" + processInstanceId + "]"; + } + + public Builder update() { + return new Builder(this); + } + + public static Builder create() { + return new Builder(new UserTaskInstanceStateEventBody()); + } + + @Override + public int hashCode() { + return Objects.hash(userTaskInstanceId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UserTaskInstanceStateEventBody other = (UserTaskInstanceStateEventBody) obj; + return Objects.equals(userTaskInstanceId, other.userTaskInstanceId); + } + + public static class Builder { + + private UserTaskInstanceStateEventBody instance; + + private Builder(UserTaskInstanceStateEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventUser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder userTaskDefinitionId(String userTaskDefinitionId) { + this.instance.userTaskDefinitionId = userTaskDefinitionId; + return this; + } + + public Builder userTaskInstanceId(String userTaskInstanceId) { + this.instance.userTaskInstanceId = userTaskInstanceId; + return this; + } + + public Builder userTaskName(String userTaskName) { + this.instance.userTaskName = userTaskName; + return this; + } + + public Builder eventType(Integer eventType) { + this.instance.eventType = eventType; + return this; + } + + public Builder userTaskDescription(String userTaskDescription) { + this.instance.userTaskDescription = userTaskDescription; + return this; + } + + public Builder userTaskPriority(String userTaskPriority) { + this.instance.userTaskPriority = userTaskPriority; + return this; + } + + public Builder userTaskReferenceName(String userTaskReferenceName) { + this.instance.userTaskReferenceName = userTaskReferenceName; + return this; + } + + public Builder state(String state) { + this.instance.state = state; + return this; + } + + public Builder actualOwner(String userId) { + this.instance.actualOwner = userId; + return this; + } + + public Builder processInstanceId(String processInstanceId) { + this.instance.processInstanceId = processInstanceId; + return this; + } + + public UserTaskInstanceStateEventBody build() { + return this.instance; + } + } +} diff --git a/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceVariableEventBody.java b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceVariableEventBody.java new file mode 100644 index 00000000000..05b440e0f38 --- /dev/null +++ b/api/kogito-events-api/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceVariableEventBody.java @@ -0,0 +1,167 @@ +/* + * 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.event.usertask; + +import java.util.Date; +import java.util.Objects; + +public class UserTaskInstanceVariableEventBody { + + // common fields for events + private Date eventDate; + private String eventUser; + + private String userTaskDefinitionId; + private String userTaskInstanceId; + private String userTaskName; + + // custom data fields + private String variableType; // input / output + private String variableId; // id + private String variableName; // name + private Object variableValue; + + public Date getEventDate() { + return eventDate; + } + + public String getEventUser() { + return eventUser; + } + + public String getUserTaskDefinitionId() { + return userTaskDefinitionId; + } + + public String getUserTaskInstanceId() { + return userTaskInstanceId; + } + + public String getUserTaskName() { + return userTaskName; + } + + public String getVariableType() { + return variableType; + } + + public String getVariableId() { + return variableId; + } + + public String getVariableName() { + return variableName; + } + + public Object getVariableValue() { + return variableValue; + } + + @Override + public String toString() { + return "UserTaskInstanceVariableEventBody [eventDate=" + eventDate + ", eventUser=" + eventUser + ", userTaskDefinitionId=" + userTaskDefinitionId + ", userTaskInstanceId=" + + userTaskInstanceId + ", userTaskName=" + userTaskName + ", variableType=" + variableType + ", variableId=" + variableId + ", variableName=" + variableName + ", variableValue=" + + variableValue + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(eventDate, userTaskDefinitionId, userTaskInstanceId, variableId, variableValue); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UserTaskInstanceVariableEventBody other = (UserTaskInstanceVariableEventBody) obj; + return Objects.equals(eventDate, other.eventDate) && Objects.equals(userTaskDefinitionId, other.userTaskDefinitionId) && Objects.equals(userTaskInstanceId, other.userTaskInstanceId) + && Objects.equals(variableId, other.variableId) && Objects.equals(variableValue, other.variableValue); + } + + public static Builder create() { + return new Builder(new UserTaskInstanceVariableEventBody()); + } + + public static class Builder { + + private UserTaskInstanceVariableEventBody instance; + + private Builder(UserTaskInstanceVariableEventBody instance) { + this.instance = instance; + } + + public Builder eventDate(Date eventDate) { + this.instance.eventDate = eventDate; + return this; + } + + public Builder eventuser(String userId) { + this.instance.eventUser = userId; + return this; + } + + public Builder userTaskDefinitionId(String userTaskDefinitionId) { + this.instance.userTaskDefinitionId = userTaskDefinitionId; + return this; + } + + public Builder userTaskInstanceId(String userTaskInstanceId) { + this.instance.userTaskInstanceId = userTaskInstanceId; + return this; + } + + public Builder userTaskName(String userTaskName) { + this.instance.userTaskName = userTaskName; + return this; + } + + public Builder variableType(String variableType) { + this.instance.variableType = variableType; + return this; + } + + public Builder variableId(String variableId) { + this.instance.variableId = variableId; + return this; + } + + public Builder variableName(String variableName) { + this.instance.variableName = variableName; + return this; + } + + public Builder variableValue(Object variableValue) { + this.instance.variableValue = variableValue; + return this; + } + + public Builder eventUser(String eventUser) { + this.instance.eventUser = eventUser; + return this; + } + + public UserTaskInstanceVariableEventBody build() { + return this.instance; + } + } +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/AbstractDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/AbstractDataEvent.java index 003d6221bf0..2fcdd704196 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/AbstractDataEvent.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/AbstractDataEvent.java @@ -54,6 +54,8 @@ import io.cloudevents.core.v03.CloudEventV03; import io.cloudevents.core.v1.CloudEventV1; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + /** * This is an implementation of the {@link DataEvent} that contains basic common attributes referring to * kogito processes metadata. @@ -61,6 +63,7 @@ * @param the payload class type */ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(NON_NULL) public abstract class AbstractDataEvent implements DataEvent { /** @@ -556,7 +559,7 @@ public int hashCode() { @Override public String toString() { - return "AbstractDataEvent{" + + return getClass().getSimpleName() + " {" + "specVersion=" + specVersion + ", id='" + id + '\'' + ", source=" + source + diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/DataEventFactory.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/DataEventFactory.java index b15dcc555d5..a52df39f9df 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/DataEventFactory.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/DataEventFactory.java @@ -25,7 +25,7 @@ import org.kie.kogito.event.cloudevents.extension.ProcessMeta; import org.kie.kogito.event.impl.CloudEventWrapDataEvent; -import org.kie.kogito.event.process.ProcessDataEvent; +import org.kie.kogito.event.process.ProcessInstanceDataEvent; import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; import io.cloudevents.CloudEvent; @@ -36,7 +36,7 @@ public class DataEventFactory { public static DataEvent from(T event) { - return new ProcessDataEvent<>(event); + return new ProcessInstanceDataEvent<>(event); } public static DataEvent from(CloudEvent event, Converter dataUnmarshaller) { @@ -48,7 +48,7 @@ public static DataEvent from(T eventData, String trigger, KogitoProcessIn } public static DataEvent from(T eventData, String type, URI source, Optional subject, CloudEventExtension... extensions) { - ProcessDataEvent ce = new ProcessDataEvent<>(eventData); + ProcessInstanceDataEvent ce = new ProcessInstanceDataEvent<>(eventData); ce.setSpecVersion(SpecVersion.V1); ce.setId(UUID.randomUUID().toString()); ce.setType(type); diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/BaseEventManager.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/BaseEventManager.java index fa25bb4c044..60d02a96d46 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/BaseEventManager.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/BaseEventManager.java @@ -27,9 +27,13 @@ import org.kie.kogito.event.EventBatch; import org.kie.kogito.event.EventManager; import org.kie.kogito.event.EventPublisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BaseEventManager implements EventManager { + private static final Logger logger = LoggerFactory.getLogger(BaseEventManager.class); + private String service; private Addons addons; private Set publishers = new LinkedHashSet<>(); @@ -47,6 +51,10 @@ public void publish(EventBatch batch) { } Collection> events = batch.events(); + for (DataEvent event : events) { + logger.debug("publishing {}", event); + } + publishers.forEach(p -> p.publish(events)); } diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitQueryRestCodegen.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessEventBatch.java similarity index 52% rename from kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitQueryRestCodegen.java rename to api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessEventBatch.java index b8705d7443d..fca70c09800 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitQueryRestCodegen.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessEventBatch.java @@ -16,31 +16,30 @@ * specific language governing permissions and limitations * under the License. */ -package org.kie.kogito.codegen.rules; +package org.kie.kogito.event.impl; +import java.util.ArrayList; import java.util.Collection; -import java.util.stream.Collectors; +import java.util.Collections; +import java.util.List; -import org.drools.codegen.common.GeneratedFile; +import org.kie.kogito.event.DataEvent; +import org.kie.kogito.event.EventBatch; -public class RuleUnitQueryRestCodegen { +public class ProcessEventBatch implements EventBatch { - private final Collection endpointGenerators; + private List> events = Collections.synchronizedList(new ArrayList<>()); - public RuleUnitQueryRestCodegen(Collection validQueries) { - this.endpointGenerators = - validQueries.stream().map(QueryEndpointGenerator::new) - .collect(Collectors.toUnmodifiableList()); + @Override + public void append(Object rawEvent) { + if (!DataEvent.class.isInstance(rawEvent)) { + throw new IllegalArgumentException("The event is not a ProcessDataEvent"); + } + events.add((DataEvent) rawEvent); } - Collection endpointGenerators() { - return endpointGenerators; + @Override + public Collection> events() { + return events; } - - Collection generate() { - return endpointGenerators.stream() - .map(QueryEndpointGenerator::generate) - .collect(Collectors.toUnmodifiableList()); - } - } diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessInstanceEventBatch.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessInstanceEventBatch.java index 56f8a975988..3991c65da02 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessInstanceEventBatch.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/ProcessInstanceEventBatch.java @@ -20,293 +20,436 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.Date; +import java.util.HashMap; import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; import org.kie.api.event.process.ProcessCompletedEvent; import org.kie.api.event.process.ProcessEvent; import org.kie.api.event.process.ProcessNodeEvent; import org.kie.api.event.process.ProcessNodeLeftEvent; import org.kie.api.event.process.ProcessNodeTriggeredEvent; +import org.kie.api.event.process.ProcessStartedEvent; import org.kie.api.event.process.ProcessVariableChangedEvent; +import org.kie.api.event.process.SLAViolatedEvent; +import org.kie.api.event.usertask.UserTaskAssignmentEvent; +import org.kie.api.event.usertask.UserTaskAttachmentEvent; +import org.kie.api.event.usertask.UserTaskCommentEvent; +import org.kie.api.event.usertask.UserTaskDeadlineEvent; +import org.kie.api.event.usertask.UserTaskEvent; +import org.kie.api.event.usertask.UserTaskStateEvent; +import org.kie.api.event.usertask.UserTaskVariableEvent; import org.kie.kogito.Addons; import org.kie.kogito.event.DataEvent; import org.kie.kogito.event.EventBatch; -import org.kie.kogito.event.process.AttachmentEventBody; -import org.kie.kogito.event.process.CommentEventBody; -import org.kie.kogito.event.process.MilestoneEventBody; -import org.kie.kogito.event.process.NodeInstanceEventBody; -import org.kie.kogito.event.process.ProcessErrorEventBody; -import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.UserTaskDeadlineDataEvent; -import org.kie.kogito.event.process.UserTaskDeadlineEventBody; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceEventBody; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; -import org.kie.kogito.internal.process.event.HumanTaskDeadlineEvent; -import org.kie.kogito.internal.process.event.KogitoProcessVariableChangedEvent; -import org.kie.kogito.internal.process.event.ProcessWorkItemTransitionEvent; -import org.kie.kogito.internal.process.runtime.KogitoNodeInstance; +import org.kie.kogito.event.process.ProcessInstanceErrorDataEvent; +import org.kie.kogito.event.process.ProcessInstanceErrorEventBody; +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; +import org.kie.kogito.event.process.ProcessInstanceNodeDataEvent; +import org.kie.kogito.event.process.ProcessInstanceNodeEventBody; +import org.kie.kogito.event.process.ProcessInstanceSLADataEvent; +import org.kie.kogito.event.process.ProcessInstanceSLAEventBody; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateEventBody; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; +import org.kie.kogito.event.process.ProcessInstanceVariableEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceAssignmentDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceAssignmentEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceAttachmentDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceAttachmentEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceCommentDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceCommentEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceEventMetadata; +import org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceStateEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceVariableDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceVariableEventBody; import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; -import org.kie.kogito.internal.process.runtime.KogitoWorkItem; import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcessInstance; -import org.kie.kogito.process.workitem.Attachment; -import org.kie.kogito.process.workitem.Comment; import org.kie.kogito.process.workitem.HumanTaskWorkItem; -import static java.util.stream.Collectors.toList; - public class ProcessInstanceEventBatch implements EventBatch { - private final String service; + private String service; private Addons addons; - private List rawEvents = new ArrayList<>(); + Collection> processedEvents; public ProcessInstanceEventBatch(String service, Addons addons) { this.service = service; - this.addons = addons; + this.addons = addons != null ? addons : Addons.EMTPY; + this.processedEvents = new ArrayList<>(); } @Override public void append(Object rawEvent) { if (rawEvent instanceof ProcessEvent) { - rawEvents.add((ProcessEvent) rawEvent); + addDataEvent((ProcessEvent) rawEvent); + } else if (rawEvent instanceof UserTaskEvent) { + addDataEvent((UserTaskEvent) rawEvent); } } @Override public Collection> events() { - Map processInstances = new LinkedHashMap<>(); - Map userTaskInstances = new LinkedHashMap<>(); - Set variables = new LinkedHashSet<>(); - - Collection> processedEvents = new ArrayList<>(); - for (ProcessEvent event : rawEvents) { - ProcessInstanceEventBody body = processInstances.computeIfAbsent(((KogitoProcessInstance) event.getProcessInstance()).getStringId(), key -> create(event)); - - if (event instanceof ProcessNodeTriggeredEvent) { - handleProcessNodeTriggeredEvent((ProcessNodeTriggeredEvent) event, body); - } else if (event instanceof ProcessNodeLeftEvent) { - handleProcessNodeLeftEvent((ProcessNodeLeftEvent) event, body); - } else if (event instanceof ProcessCompletedEvent) { - handleProcessCompletedEvent((ProcessCompletedEvent) event, body); - } else if (event instanceof ProcessWorkItemTransitionEvent) { - handleProcessWorkItemTransitionEvent((ProcessWorkItemTransitionEvent) event, userTaskInstances); - } else if (event instanceof ProcessVariableChangedEvent) { - handleProcessVariableChangedEvent((KogitoProcessVariableChangedEvent) event, variables); - } else if (event instanceof HumanTaskDeadlineEvent) { - processedEvents.add(buildUserTaskDeadlineEvent((HumanTaskDeadlineEvent) event)); - } - } - processInstances.values().stream().map(pi -> new ProcessInstanceDataEvent(extractRuntimeSource(pi.metaData()), addons.toString(), pi.getIdentity(), pi.metaData(), pi)) - .forEach(processedEvents::add); - userTaskInstances.values().stream().map(pi -> new UserTaskInstanceDataEvent(extractRuntimeSource(pi.metaData()), addons.toString(), pi.getIdentity(), pi.metaData(), pi)) - .forEach(processedEvents::add); - variables.stream().map(pi -> new VariableInstanceDataEvent(extractRuntimeSource(pi.metaData()), addons.toString(), pi.getIdentity(), pi.metaData(), pi)).forEach(processedEvents::add); return processedEvents; } - private DataEvent buildUserTaskDeadlineEvent(HumanTaskDeadlineEvent event) { - HumanTaskWorkItem workItem = event.getWorkItem(); - KogitoWorkflowProcessInstance pi = (KogitoWorkflowProcessInstance) event.getProcessInstance(); - UserTaskDeadlineEventBody body = UserTaskDeadlineEventBody.create(workItem.getStringId(), event - .getNotification()) - .state(workItem.getPhaseStatus()) - .taskName(workItem.getTaskName()) - .taskDescription(workItem.getTaskDescription()) - .taskPriority(workItem.getTaskPriority()) - .referenceName(workItem.getReferenceName()) - .actualOwner(workItem.getActualOwner()) - .startDate(workItem.getStartDate()) - .processInstanceId(pi.getStringId()) - .rootProcessInstanceId(pi.getRootProcessInstanceId()) - .processId(pi.getProcessId()) - .rootProcessId(pi.getRootProcessId()) - .inputs(workItem.getParameters()) - .outputs(workItem.getResults()).build(); - return new UserTaskDeadlineDataEvent("UserTaskDeadline" + event.getType(), buildSource(pi.getProcessId()), - addons.toString(), event.getEventIdentity(), body, pi.getStringId(), pi.getRootProcessInstanceId(), pi.getProcessId(), pi - .getRootProcessId()); + private void addDataEvent(ProcessEvent event) { + // process events + if (event instanceof ProcessStartedEvent) { + handleProcessStateEvent((ProcessStartedEvent) event); + } else if (event instanceof ProcessCompletedEvent) { + handleProcessStateEvent((ProcessCompletedEvent) event); + } else if (event instanceof ProcessNodeTriggeredEvent) { + handleProcesssNodeEvent((ProcessNodeTriggeredEvent) event); + } else if (event instanceof ProcessNodeLeftEvent) { + handleProcesssNodeEvent((ProcessNodeLeftEvent) event); + } else if (event instanceof SLAViolatedEvent) { + handleProcesssNodeEvent((SLAViolatedEvent) event); + } else if (event instanceof ProcessVariableChangedEvent) { + handleProcesssVariableEvent((ProcessVariableChangedEvent) event); + } } - protected void handleProcessCompletedEvent(ProcessCompletedEvent event, ProcessInstanceEventBody body) { - // in case this is a process complete event always updated and date and state - body.update() - .endDate(((KogitoWorkflowProcessInstance) event.getProcessInstance()).getEndDate()) - .state(event.getProcessInstance().getState()); - } + private void handleProcesssVariableEvent(ProcessVariableChangedEvent event) { + // custom data fields for this event that are not there + // private String nodeContainerDefinitionId; + // private String nodeContainerInstanceId; - protected void handleProcessNodeTriggeredEvent(ProcessNodeTriggeredEvent event, ProcessInstanceEventBody body) { - NodeInstanceEventBody nodeInstanceBody = create(event); - if (!body.getNodeInstances().contains(nodeInstanceBody)) { - // add it only if it does not exist - body.update().nodeInstance(nodeInstanceBody); - } - } + Map metadata = buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance()); - protected void handleProcessNodeLeftEvent(ProcessNodeLeftEvent event, ProcessInstanceEventBody body) { - NodeInstanceEventBody nodeInstanceBody = create(event); - // if it's already there, remove it - body.getNodeInstances().remove(nodeInstanceBody); - // and add it back as the node left event has latest information - body.update().nodeInstance(nodeInstanceBody); - } + ProcessInstanceVariableEventBody.Builder builder = ProcessInstanceVariableEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventIdentity()) + .processId(event.getProcessInstance().getProcessId()) + .processVersion(event.getProcessInstance().getProcessVersion()) + .processInstanceId(event.getProcessInstance().getId()) + .variableId(event.getVariableInstanceId()) + .variableName(event.getVariableId()) + .variableValue(event.getNewValue()); - protected void handleProcessWorkItemTransitionEvent(ProcessWorkItemTransitionEvent workItemTransitionEvent, Map userTaskInstances) { - KogitoWorkItem workItem = workItemTransitionEvent.getWorkItem(); - if (workItem instanceof HumanTaskWorkItem && workItemTransitionEvent.isTransitioned()) { - userTaskInstances.putIfAbsent(workItem.getStringId(), createUserTask(workItemTransitionEvent)); - } + ProcessInstanceVariableEventBody body = builder.build(); + processedEvents.add(new ProcessInstanceVariableDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventIdentity(), metadata, body)); } - protected void handleProcessVariableChangedEvent(KogitoProcessVariableChangedEvent variableChangedEvent, Set variables) { - if (!variableChangedEvent.hasTag("internal")) { - variables.add(create(variableChangedEvent)); + private void handleProcesssNodeEvent(SLAViolatedEvent event) { + Map metadata = buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance()); + + ProcessInstanceSLAEventBody.Builder builder = ProcessInstanceSLAEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventIdentity()) + .processId(event.getProcessInstance().getProcessId()) + .processVersion(event.getProcessInstance().getProcessVersion()) + .processInstanceId(event.getProcessInstance().getId()); + + if (event.getNodeInstance() != null) { + builder.nodeDefinitionId(event.getNodeInstance().getNode().getNodeUniqueId()) + .nodeInstanceId(event.getNodeInstance().getId()); } + + ProcessInstanceSLAEventBody body = builder.build(); + processedEvents.add(new ProcessInstanceSLADataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventIdentity(), metadata, body)); } - protected UserTaskInstanceEventBody createUserTask(ProcessWorkItemTransitionEvent workItemTransitionEvent) { - KogitoWorkflowProcessInstance pi = (KogitoWorkflowProcessInstance) workItemTransitionEvent.getProcessInstance(); - HumanTaskWorkItem workItem = (HumanTaskWorkItem) workItemTransitionEvent.getWorkItem(); - return UserTaskInstanceEventBody.create() - .id(workItem.getStringId()) - .state(workItem.getPhaseStatus()) - .taskName(workItem.getTaskName()) - .taskDescription(workItem.getTaskDescription()) - .taskPriority(workItem.getTaskPriority()) - .referenceName(workItem.getReferenceName()) - .actualOwner(workItem.getActualOwner()) - .startDate(workItem.getStartDate()) - .completeDate(workItem.getCompleteDate()) - .adminGroups(workItem.getAdminGroups()) - .adminUsers(workItem.getAdminUsers()) - .excludedUsers(workItem.getExcludedUsers()) - .potentialGroups(workItem.getPotentialGroups()) - .potentialUsers(workItem.getPotentialUsers()) - .processInstanceId(pi.getStringId()) - .processInstanceVersion(pi.getProcess().getVersion()) - .rootProcessInstanceId(pi.getRootProcessInstanceId()) - .processId(pi.getProcessId()) - .rootProcessId(pi.getRootProcessId()) - .inputs(workItem.getParameters()) - .outputs(workItem.getResults()) - .comments(workItem.getComments().values().stream().map(createComment()).collect(toList())) - .attachments(workItem.getAttachments().values().stream().map(createAttachment()).collect(toList())) - .identity(workItemTransitionEvent.getEventIdentity()) - .build(); + private void handleProcesssNodeEvent(ProcessNodeLeftEvent event) { + processedEvents.add(toProcessInstanceNodeEvent(event, ProcessInstanceNodeEventBody.EVENT_TYPE_EXIT)); } - protected Function createComment() { - return comment -> CommentEventBody.create() - .id(comment.getId()) - .content(comment.getContent()) - .updatedAt(comment.getUpdatedAt()) - .updatedBy(comment.getUpdatedBy()) - .build(); + private void handleProcesssNodeEvent(ProcessNodeTriggeredEvent event) { + processedEvents.add(toProcessInstanceNodeEvent(event, ProcessInstanceNodeEventBody.EVENT_TYPE_ENTER)); + } - protected Function createAttachment() { - return attachment -> AttachmentEventBody.create() - .id(attachment.getId()) - .name(attachment.getName()) - .content(attachment.getContent()) - .updatedAt(attachment.getUpdatedAt()) - .updatedBy(attachment.getUpdatedBy()) - .build(); + private ProcessInstanceNodeDataEvent toProcessInstanceNodeEvent(ProcessNodeEvent event, int eventType) { + Map metadata = buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance()); + + ProcessInstanceNodeEventBody.Builder builder = ProcessInstanceNodeEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventIdentity()) + .eventType(eventType) + .processId(event.getProcessInstance().getProcessId()) + .processVersion(event.getProcessInstance().getProcessVersion()) + .processInstanceId(event.getProcessInstance().getId()) + .nodeName(event.getNodeInstance().getNodeName()) + .nodeType(event.getNodeInstance().getNode().getClass().getSimpleName()) + .nodeInstanceId(event.getNodeInstance().getId()) + .nodeDefinitionId(event.getNodeInstance().getNode().getNodeUniqueId()); + + ProcessInstanceNodeEventBody body = builder.build(); + return new ProcessInstanceNodeDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventIdentity(), metadata, body); } - protected ProcessInstanceEventBody create(ProcessEvent event) { + private void handleProcessStateEvent(ProcessCompletedEvent event) { + + processedEvents.add(toProcessInstanceStateEvent(event, ProcessInstanceStateEventBody.EVENT_TYPE_ENDED)); + KogitoWorkflowProcessInstance pi = (KogitoWorkflowProcessInstance) event.getProcessInstance(); + if (pi.getState() == KogitoProcessInstance.STATE_ERROR) { + ProcessInstanceErrorEventBody errorBody = ProcessInstanceErrorEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventIdentity()) + .processInstanceId(pi.getId()) + .processId(pi.getProcessId()) + .processVersion(pi.getProcessVersion()) + .nodeDefinitionId(pi.getNodeIdInError()) + .errorMessage(pi.getErrorMessage()) + .build(); + Map metadata = buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance()); + processedEvents.add(new ProcessInstanceErrorDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventIdentity(), metadata, errorBody)); + } + } - ProcessInstanceEventBody.Builder eventBuilder = ProcessInstanceEventBody.create() - .id(pi.getStringId()) - .version(pi.getProcess().getVersion()) - .parentInstanceId(pi.getParentProcessInstanceId()) - .rootInstanceId(pi.getRootProcessInstanceId()) - .processId(pi.getProcessId()) - .rootProcessId(pi.getRootProcessId()) - .processName(pi.getProcessName()) - .startDate(pi.getStartDate()) - .endDate(pi.getEndDate()) - .state(pi.getState()) - .businessKey(pi.getCorrelationKey()) - .variables(pi.getVariables()) - .milestones(createMilestones(pi)) - .identity(event.getEventIdentity()); + private void handleProcessStateEvent(ProcessStartedEvent event) { + processedEvents.add(toProcessInstanceStateEvent(event, ProcessInstanceStateEventBody.EVENT_TYPE_STARTED)); + KogitoWorkflowProcessInstance pi = (KogitoWorkflowProcessInstance) event.getProcessInstance(); if (pi.getState() == KogitoProcessInstance.STATE_ERROR) { - eventBuilder.error(ProcessErrorEventBody.create() + ProcessInstanceErrorEventBody errorBody = ProcessInstanceErrorEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventIdentity()) + .processInstanceId(pi.getId()) + .processId(pi.getProcessId()) + .processVersion(pi.getProcessVersion()) .nodeDefinitionId(pi.getNodeIdInError()) .errorMessage(pi.getErrorMessage()) - .build()); + .build(); + Map metadata = buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance()); + processedEvents.add(new ProcessInstanceErrorDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventIdentity(), metadata, errorBody)); } - String securityRoles = (String) pi.getProcess().getMetaData().get("securityRoles"); + } + + private ProcessInstanceStateDataEvent toProcessInstanceStateEvent(ProcessEvent event, int eventType) { + Map metadata = buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance()); + + KogitoWorkflowProcessInstance pi = (KogitoWorkflowProcessInstance) event.getProcessInstance(); + + ProcessInstanceStateEventBody.Builder builder = ProcessInstanceStateEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventIdentity()) + .eventType(eventType) + .processId(event.getProcessInstance().getProcessId()) + .processVersion(event.getProcessInstance().getProcessVersion()) + .processInstanceId(event.getProcessInstance().getId()) + .processName(event.getProcessInstance().getProcessName()) + .processVersion(event.getProcessInstance().getProcessVersion()) + .processType(event.getProcessInstance().getProcess().getType()) + .parentInstanceId(pi.getParentProcessInstanceId()) + .rootProcessId(pi.getRootProcessId()) + .rootProcessInstanceId(pi.getRootProcessInstanceId()) + .state(event.getProcessInstance().getState()); + + String securityRoles = (String) event.getProcessInstance().getProcess().getMetaData().get("securityRoles"); if (securityRoles != null) { - eventBuilder.roles(securityRoles.split(",")); + builder.roles(securityRoles.split(",")); } - return eventBuilder.build(); + ProcessInstanceStateEventBody body = builder.build(); + return new ProcessInstanceStateDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventIdentity(), metadata, body); + } + + private Map buildProcessMetadata(KogitoWorkflowProcessInstance pi) { + Map metadata = new HashMap<>(); + metadata.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA, pi.getId()); + metadata.put(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA, pi.getProcessVersion()); + metadata.put(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA, pi.getProcessId()); + metadata.put(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA, String.valueOf(pi.getState())); + metadata.put(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA, pi.getProcess().getType()); + metadata.put(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA, pi.getParentProcessInstanceId()); + metadata.put(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA, pi.getRootProcessId()); + metadata.put(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA, pi.getRootProcessInstanceId()); + return metadata; + } + + private void addDataEvent(UserTaskEvent event) { + // this should go in another event types + if (event instanceof UserTaskStateEvent) { + handleUserTaskStateEvent((UserTaskStateEvent) event); + } else if (event instanceof UserTaskDeadlineEvent) { + handleUserTaskDeadlineEvent((UserTaskDeadlineEvent) event); + } else if (event instanceof UserTaskAssignmentEvent) { + handleUserTaskAssignmentEvent((UserTaskAssignmentEvent) event); + } else if (event instanceof UserTaskVariableEvent) { + handleUserTaskVariableEvent((UserTaskVariableEvent) event); + } else if (event instanceof UserTaskAttachmentEvent) { + handleUserTaskAttachmentEvent((UserTaskAttachmentEvent) event); + } else if (event instanceof UserTaskCommentEvent) { + handleUserTaskCommentEvent((UserTaskCommentEvent) event); + } } - protected Set createMilestones(KogitoWorkflowProcessInstance pi) { - if (pi.milestones() == null) { - return Collections.emptySet(); + private void handleUserTaskCommentEvent(UserTaskCommentEvent event) { + Map metadata = buildUserTaskMetadata((HumanTaskWorkItem) event.getWorkItem()); + metadata.putAll(buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance())); + + int eventType = UserTaskInstanceCommentEventBody.EVENT_TYPE_ADDED; + if (event.getOldComment() != null && event.getNewComment() == null) { + eventType = UserTaskInstanceCommentEventBody.EVENT_TYPE_DELETED; + } else if (event.getOldComment() != null && event.getNewComment() != null) { + eventType = UserTaskInstanceCommentEventBody.EVENT_TYPE_CHANGE; + } + + UserTaskInstanceCommentEventBody.Builder builder = UserTaskInstanceCommentEventBody.create() + .eventType(eventType) + .userTaskDefinitionId(event.getUserTaskDefinitionId()) + .userTaskInstanceId(((HumanTaskWorkItem) event.getWorkItem()).getStringId()) + .userTaskName(((HumanTaskWorkItem) event.getWorkItem()).getTaskName()); + + String updatedBy = null; + switch (eventType) { + case UserTaskInstanceCommentEventBody.EVENT_TYPE_ADDED: + case UserTaskInstanceCommentEventBody.EVENT_TYPE_CHANGE: + builder.commentContent(event.getNewComment().getCommentContent()) + .commentId(event.getNewComment().getCommentId()) + .eventDate(event.getNewComment().getUpdatedAt()) + .eventUser(event.getNewComment().getUpdatedBy()); + updatedBy = event.getNewComment().getUpdatedBy(); + break; + case UserTaskInstanceCommentEventBody.EVENT_TYPE_DELETED: + builder.commentId(event.getOldComment().getCommentId()) + .eventDate(event.getOldComment().getUpdatedAt()) + .eventUser(event.getOldComment().getUpdatedBy()); + + updatedBy = event.getOldComment().getUpdatedBy(); + break; } - return pi.milestones().stream() - .map(m -> MilestoneEventBody.create().id(m.getId()).name(m.getName()).status(m.getStatus().name()).build()) - .collect(Collectors.toSet()); + UserTaskInstanceCommentEventBody body = builder.build(); + processedEvents.add(new UserTaskInstanceCommentDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), updatedBy, metadata, body)); + } - protected NodeInstanceEventBody create(ProcessNodeEvent event) { - KogitoNodeInstance ni = (KogitoNodeInstance) event.getNodeInstance(); - - return NodeInstanceEventBody.create() - .id(ni.getStringId()) - .nodeId(String.valueOf(ni.getNodeId())) - .nodeDefinitionId(ni.getNodeDefinitionId()) - .nodeName(ni.getNodeName()) - .nodeType(ni.getNode().getClass().getSimpleName()) - .triggerTime(ni.getTriggerTime()) - .leaveTime(ni.getLeaveTime()) - .build(); + private void handleUserTaskAttachmentEvent(UserTaskAttachmentEvent event) { + Map metadata = buildUserTaskMetadata((HumanTaskWorkItem) event.getWorkItem()); + metadata.putAll(buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance())); + + int eventType = UserTaskInstanceAttachmentEventBody.EVENT_TYPE_ADDED; + if (event.getOldAttachment() != null && event.getNewAttachment() == null) { + eventType = UserTaskInstanceAttachmentEventBody.EVENT_TYPE_DELETED; + } else if (event.getOldAttachment() != null && event.getNewAttachment() != null) { + eventType = UserTaskInstanceAttachmentEventBody.EVENT_TYPE_CHANGE; + } + + UserTaskInstanceAttachmentEventBody.Builder builder = UserTaskInstanceAttachmentEventBody.create() + .eventType(eventType) + .userTaskDefinitionId(event.getUserTaskDefinitionId()) + .userTaskInstanceId(((HumanTaskWorkItem) event.getWorkItem()).getStringId()) + .userTaskName(((HumanTaskWorkItem) event.getWorkItem()).getTaskName()); + + String updatedBy = null; + switch (eventType) { + case UserTaskInstanceAttachmentEventBody.EVENT_TYPE_ADDED: + case UserTaskInstanceAttachmentEventBody.EVENT_TYPE_CHANGE: + builder.attachmentName(event.getNewAttachment().getAttachmentName()) + .attachmentId(event.getNewAttachment().getAttachmentId()) + .attachmentURI(event.getNewAttachment().getAttachmentURI()) + .eventDate(event.getNewAttachment().getUpdatedAt()) + .eventUser(event.getNewAttachment().getUpdatedBy()); + updatedBy = event.getNewAttachment().getUpdatedBy(); + + break; + case UserTaskInstanceAttachmentEventBody.EVENT_TYPE_DELETED: + builder.attachmentId(event.getOldAttachment().getAttachmentId()) + .eventDate(event.getOldAttachment().getUpdatedAt()) + .eventUser(event.getOldAttachment().getUpdatedBy()); + updatedBy = event.getOldAttachment().getUpdatedBy(); + break; + } + + UserTaskInstanceAttachmentEventBody body = builder.build(); + processedEvents + .add(new UserTaskInstanceAttachmentDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), updatedBy, metadata, body)); + } - protected VariableInstanceEventBody create(KogitoProcessVariableChangedEvent event) { - KogitoProcessInstance pi = (KogitoProcessInstance) event.getProcessInstance(); + private void handleUserTaskAssignmentEvent(UserTaskAssignmentEvent event) { + Map metadata = buildUserTaskMetadata((HumanTaskWorkItem) event.getWorkItem()); + metadata.putAll(buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance())); + + UserTaskInstanceAssignmentEventBody.Builder builder = UserTaskInstanceAssignmentEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventUser()) + .userTaskDefinitionId(event.getUserTaskDefinitionId()) + .userTaskInstanceId(((HumanTaskWorkItem) event.getWorkItem()).getStringId()) + .userTaskName(((HumanTaskWorkItem) event.getWorkItem()).getTaskName()) + .assignmentType(event.getAssignmentType()) + .users(event.getNewUsersId()); + + UserTaskInstanceAssignmentEventBody body = builder.build(); + processedEvents.add(new UserTaskInstanceAssignmentDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventUser(), metadata, body)); + } - VariableInstanceEventBody.Builder eventBuilder = VariableInstanceEventBody.create() - .changeDate(event.getEventDate()) - .processId(pi.getProcessId()) - .processInstanceId(pi.getStringId()) - .rootProcessId(pi.getRootProcessId()) - .rootProcessInstanceId(pi.getRootProcessInstanceId()) - .variableName(event.getVariableId()) + private void handleUserTaskDeadlineEvent(UserTaskDeadlineEvent event) { + Map metadata = buildUserTaskMetadata((HumanTaskWorkItem) event.getWorkItem()); + metadata.putAll(buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance())); + + UserTaskInstanceDeadlineEventBody.Builder builder = UserTaskInstanceDeadlineEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventUser()) + .userTaskDefinitionId(event.getUserTaskDefinitionId()) + .userTaskInstanceId(((HumanTaskWorkItem) event.getWorkItem()).getStringId()) + .userTaskName(((HumanTaskWorkItem) event.getWorkItem()).getTaskName()) + .notification(event.getNotification()); + + UserTaskInstanceDeadlineEventBody body = builder.build(); + processedEvents.add(new UserTaskInstanceDeadlineDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventUser(), metadata, body)); + } + + private void handleUserTaskStateEvent(UserTaskStateEvent event) { + Map metadata = buildUserTaskMetadata((HumanTaskWorkItem) event.getWorkItem()); + metadata.putAll(buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance())); + + UserTaskInstanceStateEventBody.Builder builder = UserTaskInstanceStateEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventUser()) + .userTaskDefinitionId(event.getUserTaskDefinitionId()) + .userTaskInstanceId(((HumanTaskWorkItem) event.getWorkItem()).getStringId()) + .userTaskName(((HumanTaskWorkItem) event.getWorkItem()).getTaskName()) + .userTaskDescription(((HumanTaskWorkItem) event.getWorkItem()).getTaskDescription()) + .userTaskPriority(((HumanTaskWorkItem) event.getWorkItem()).getTaskPriority()) + .userTaskReferenceName(((HumanTaskWorkItem) event.getWorkItem()).getReferenceName()) + .state(((HumanTaskWorkItem) event.getWorkItem()).getPhaseStatus()) + .actualOwner(((HumanTaskWorkItem) event.getWorkItem()).getActualOwner()) + .processInstanceId(event.getProcessInstance().getId()); + + UserTaskInstanceStateEventBody body = builder.build(); + processedEvents.add(new UserTaskInstanceStateDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventUser(), metadata, body)); + } + + private void handleUserTaskVariableEvent(UserTaskVariableEvent event) { + Map metadata = buildUserTaskMetadata((HumanTaskWorkItem) event.getWorkItem()); + metadata.putAll(buildProcessMetadata((KogitoWorkflowProcessInstance) event.getProcessInstance())); + + UserTaskInstanceVariableEventBody.Builder builder = UserTaskInstanceVariableEventBody.create() + .eventDate(new Date()) + .eventUser(event.getEventUser()) + .userTaskDefinitionId(event.getUserTaskDefinitionId()) + .userTaskInstanceId(((HumanTaskWorkItem) event.getWorkItem()).getStringId()) + .userTaskName(((HumanTaskWorkItem) event.getWorkItem()).getTaskName()) + .variableId(event.getVariableName()) + .variableName(event.getVariableName()) .variableValue(event.getNewValue()) - .variablePreviousValue(event.getOldValue()) - .identity(event.getEventIdentity()); + .variableType(event.getVariableType().name()); - if (event.getNodeInstance() != null) { - eventBuilder - .changedByNodeId(event.getNodeInstance().getNodeDefinitionId()) - .changedByNodeName(event.getNodeInstance().getNodeName()) - .changedByNodeType(event.getNodeInstance().getNode().getClass().getSimpleName()); - } + UserTaskInstanceVariableEventBody body = builder.build(); + + processedEvents.add(new UserTaskInstanceVariableDataEvent(buildSource(event.getProcessInstance().getProcessId()), addons.toString(), event.getEventUser(), metadata, body)); + + } + + private Map buildUserTaskMetadata(HumanTaskWorkItem pi) { + Map metadata = new HashMap<>(); + metadata.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA, pi.getStringId()); + metadata.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA, pi.getReferenceName()); + metadata.put(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA, pi.getPhaseStatus()); - return eventBuilder.build(); + return metadata; } protected String extractRuntimeSource(Map metadata) { - return buildSource(metadata.get(ProcessInstanceEventBody.PROCESS_ID_META_DATA)); + return buildSource(metadata.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA)); } private String buildSource(String processId) { diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessDataEvent.java deleted file mode 100644 index 6323bbad5ef..00000000000 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessDataEvent.java +++ /dev/null @@ -1,62 +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.event.process; - -import org.kie.kogito.event.AbstractDataEvent; - -public class ProcessDataEvent extends AbstractDataEvent { - - public ProcessDataEvent() { - } - - public ProcessDataEvent(T body) { - setData(body); - } - - public ProcessDataEvent(String type, - String source, - T body, - String kogitoProcessInstanceId, - String kogitoProcessInstanceVersion, - String kogitoParentProcessInstanceId, - String kogitoRootProcessInstanceId, - String kogitoProcessId, - String kogitoRootProcessId, - String kogitoProcessInstanceState, - String kogitoAddons, - String kogitoProcessType, - String kogitoReferenceId, - String kogitoIdentity) { - super(type, - source, - body, - kogitoProcessInstanceId, - kogitoRootProcessInstanceId, - kogitoProcessId, - kogitoRootProcessId, - kogitoAddons, - kogitoIdentity); - setKogitoProcessInstanceVersion(kogitoProcessInstanceVersion); - setKogitoParentProcessInstanceId(kogitoParentProcessInstanceId); - setKogitoProcessInstanceState(kogitoProcessInstanceState); - setKogitoReferenceId(kogitoReferenceId); - setKogitoProcessType(kogitoProcessType); - } - -} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/UserTaskDeadlineDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessDefinitionDataEvent.java similarity index 60% rename from api/kogito-events-core/src/main/java/org/kie/kogito/event/process/UserTaskDeadlineDataEvent.java rename to api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessDefinitionDataEvent.java index c0ceea5d276..b58cece22f7 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/UserTaskDeadlineDataEvent.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessDefinitionDataEvent.java @@ -20,23 +20,26 @@ import org.kie.kogito.event.AbstractDataEvent; -public class UserTaskDeadlineDataEvent extends AbstractDataEvent { +public class ProcessDefinitionDataEvent extends AbstractDataEvent { + + public static final String PROCESS_DEFINITION_EVENT = "ProcessDefinitionEvent"; + + public ProcessDefinitionDataEvent() { - public UserTaskDeadlineDataEvent() { } - public UserTaskDeadlineDataEvent(String type, String source, String addons, String identity, - UserTaskDeadlineEventBody body, String processInstanceId, - String rootProcessInstanceId, String processId, String rootProcessId) { - super(type, - source, + public ProcessDefinitionDataEvent(ProcessDefinitionEventBody body) { + super(PROCESS_DEFINITION_EVENT, + body.getEndpoint(), body, - processInstanceId, - rootProcessInstanceId, - processId, - rootProcessId, - addons, - identity); + null, + null, + body.getId(), + null, + null, + null, + null, + DATA_CONTENT_TYPE, + null); } - -} +} \ No newline at end of file diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceDataEvent.java index fcd119f9bb8..8069df7ee39 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceDataEvent.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceDataEvent.java @@ -18,27 +18,45 @@ */ package org.kie.kogito.event.process; -import java.util.Map; +import org.kie.kogito.event.AbstractDataEvent; -public class ProcessInstanceDataEvent extends ProcessDataEvent { +public class ProcessInstanceDataEvent extends AbstractDataEvent { public ProcessInstanceDataEvent() { } - public ProcessInstanceDataEvent(String source, String addons, String identity, Map metaData, ProcessInstanceEventBody body) { - super("ProcessInstanceEvent", + public ProcessInstanceDataEvent(T body) { + setData(body); + } + + public ProcessInstanceDataEvent(String type, + String source, + T body, + String kogitoProcessInstanceId, + String kogitoProcessInstanceVersion, + String kogitoParentProcessInstanceId, + String kogitoRootProcessInstanceId, + String kogitoProcessId, + String kogitoRootProcessId, + String kogitoProcessInstanceState, + String kogitoAddons, + String kogitoProcessType, + String kogitoReferenceId, + String kogitoIdentity) { + super(type, source, body, - metaData.get(ProcessInstanceEventBody.ID_META_DATA), - metaData.get(ProcessInstanceEventBody.VERSION_META_DATA), - metaData.get(ProcessInstanceEventBody.PARENT_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.ROOT_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.PROCESS_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.STATE_META_DATA), - addons, - metaData.get(ProcessInstanceEventBody.PROCESS_TYPE_META_DATA), - null, - identity); + kogitoProcessInstanceId, + kogitoRootProcessInstanceId, + kogitoProcessId, + kogitoRootProcessId, + kogitoAddons, + kogitoIdentity); + setKogitoProcessInstanceVersion(kogitoProcessInstanceVersion); + setKogitoParentProcessInstanceId(kogitoParentProcessInstanceId); + setKogitoProcessInstanceState(kogitoProcessInstanceState); + setKogitoReferenceId(kogitoReferenceId); + setKogitoProcessType(kogitoProcessType); } + } diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceErrorDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceErrorDataEvent.java new file mode 100644 index 00000000000..1427e917f23 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceErrorDataEvent.java @@ -0,0 +1,44 @@ +/* + * 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.event.process; + +import java.util.Map; + +public class ProcessInstanceErrorDataEvent extends ProcessInstanceDataEvent { + + public ProcessInstanceErrorDataEvent() { + } + + public ProcessInstanceErrorDataEvent(String source, String addons, String identity, Map metaData, ProcessInstanceErrorEventBody body) { + super("ProcessInstanceErrorDataEvent", + source, + body, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + null, + identity); + } +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceNodeDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceNodeDataEvent.java new file mode 100644 index 00000000000..b58f7307ad5 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceNodeDataEvent.java @@ -0,0 +1,44 @@ +/* + * 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.event.process; + +import java.util.Map; + +public class ProcessInstanceNodeDataEvent extends ProcessInstanceDataEvent { + + public ProcessInstanceNodeDataEvent() { + } + + public ProcessInstanceNodeDataEvent(String source, String addons, String identity, Map metaData, ProcessInstanceNodeEventBody body) { + super("ProcessInstanceNodeDataEvent", + source, + body, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + null, + identity); + } +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceSLADataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceSLADataEvent.java new file mode 100644 index 00000000000..90139ce0022 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceSLADataEvent.java @@ -0,0 +1,44 @@ +/* + * 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.event.process; + +import java.util.Map; + +public class ProcessInstanceSLADataEvent extends ProcessInstanceDataEvent { + + public ProcessInstanceSLADataEvent() { + } + + public ProcessInstanceSLADataEvent(String source, String addons, String identity, Map metaData, ProcessInstanceSLAEventBody body) { + super("ProcessInstanceSLADataEvent", + source, + body, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + null, + identity); + } +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceStateDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceStateDataEvent.java new file mode 100644 index 00000000000..38d30defdab --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceStateDataEvent.java @@ -0,0 +1,44 @@ +/* + * 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.event.process; + +import java.util.Map; + +public class ProcessInstanceStateDataEvent extends ProcessInstanceDataEvent { + + public ProcessInstanceStateDataEvent() { + } + + public ProcessInstanceStateDataEvent(String source, String addons, String identity, Map metaData, ProcessInstanceStateEventBody body) { + super("ProcessInstanceStateDataEvent", + source, + body, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + null, + identity); + } +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/VariableInstanceDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceVariableDataEvent.java similarity index 67% rename from api/kogito-events-core/src/main/java/org/kie/kogito/event/process/VariableInstanceDataEvent.java rename to api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceVariableDataEvent.java index cc0a89d8ede..b7c83d367fc 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/VariableInstanceDataEvent.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/ProcessInstanceVariableDataEvent.java @@ -22,14 +22,13 @@ import java.util.Map; import java.util.Set; -import org.kie.kogito.event.AbstractDataEvent; import org.kie.kogito.event.cloudevents.CloudEventExtensionConstants; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -public class VariableInstanceDataEvent extends AbstractDataEvent { +public class ProcessInstanceVariableDataEvent extends ProcessInstanceDataEvent { private static final Set INTERNAL_EXTENSION_ATTRIBUTES = Collections.singleton(CloudEventExtensionConstants.KOGITO_VARIABLE_NAME); @@ -37,18 +36,23 @@ public class VariableInstanceDataEvent extends AbstractDataEvent metaData, VariableInstanceEventBody body) { - super("VariableInstanceEvent", + public ProcessInstanceVariableDataEvent(String source, String addons, String identity, Map metaData, ProcessInstanceVariableEventBody body) { + super("ProcessInstanceVariableDataEvent", source, body, - metaData.get(ProcessInstanceEventBody.ID_META_DATA), - metaData.get(ProcessInstanceEventBody.ROOT_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.PROCESS_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + null, identity); this.kogitoVariableName = body.getVariableName(); } diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAssignmentDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAssignmentDataEvent.java new file mode 100644 index 00000000000..0d67c6d1063 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAssignmentDataEvent.java @@ -0,0 +1,50 @@ +/* + * 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.event.usertask; + +import java.util.Map; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceAssignmentDataEvent extends UserTaskInstanceDataEvent { + + public UserTaskInstanceAssignmentDataEvent() { + } + + public UserTaskInstanceAssignmentDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceAssignmentEventBody body) { + super("UserTaskInstanceAssignmentDataEvent", + source, + body, + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA), + identity); + + } + +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAttachmentDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAttachmentDataEvent.java new file mode 100644 index 00000000000..9ed82df7e86 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceAttachmentDataEvent.java @@ -0,0 +1,50 @@ +/* + * 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.event.usertask; + +import java.util.Map; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceAttachmentDataEvent extends UserTaskInstanceDataEvent { + + public UserTaskInstanceAttachmentDataEvent() { + } + + public UserTaskInstanceAttachmentDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceAttachmentEventBody body) { + super("UserTaskInstanceAttachmentDataEvent", + source, + body, + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA), + identity); + + } + +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceCommentDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceCommentDataEvent.java new file mode 100644 index 00000000000..be67ba42810 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceCommentDataEvent.java @@ -0,0 +1,50 @@ +/* + * 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.event.usertask; + +import java.util.Map; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceCommentDataEvent extends UserTaskInstanceDataEvent { + + public UserTaskInstanceCommentDataEvent() { + } + + public UserTaskInstanceCommentDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceCommentEventBody body) { + super("UserTaskInstanceCommentDataEvent", + source, + body, + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA), + identity); + + } + +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/UserTaskInstanceDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDataEvent.java similarity index 53% rename from api/kogito-events-core/src/main/java/org/kie/kogito/event/process/UserTaskInstanceDataEvent.java rename to api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDataEvent.java index ece11c22e34..98fc6528094 100644 --- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/process/UserTaskInstanceDataEvent.java +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDataEvent.java @@ -16,9 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -package org.kie.kogito.event.process; +package org.kie.kogito.event.usertask; -import java.util.Map; import java.util.Set; import org.kie.kogito.event.AbstractDataEvent; @@ -28,50 +27,75 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -public class UserTaskInstanceDataEvent extends AbstractDataEvent { +public class UserTaskInstanceDataEvent extends AbstractDataEvent { + + private static final Set INTERNAL_EXTENSION_ATTRIBUTES = Set.of( + CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID, + CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE); @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonProperty(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID) - private String kogitoUserTaskinstanceId; + private String kogitoUserTaskInstanceId; + @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonProperty(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE) - private String kogitoUserTaskinstanceState; - - private static final Set INTERNAL_EXTENSION_ATTRIBUTES = Set.of( - CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID, - CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE); + private String kogitoUserTaskInstanceState; public UserTaskInstanceDataEvent() { } - public UserTaskInstanceDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceEventBody body) { - super("UserTaskInstanceEvent", + public UserTaskInstanceDataEvent(T body) { + setData(body); + } + + public UserTaskInstanceDataEvent(String type, + String source, + T body, + String kogitoUserTaskInstanceId, + String kogitoUserTaskInstanceState, + String kogitoProcessInstanceId, + String kogitoProcessInstanceVersion, + String kogitoParentProcessInstanceId, + String kogitoRootProcessInstanceId, + String kogitoProcessId, + String kogitoRootProcessId, + String kogitoProcessInstanceState, + String kogitoAddons, + String kogitoProcessType, + String kogitoReferenceId, + String kogitoIdentity) { + super(type, source, body, - metaData.get(ProcessInstanceEventBody.ID_META_DATA), - metaData.get(ProcessInstanceEventBody.ROOT_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.PROCESS_ID_META_DATA), - metaData.get(ProcessInstanceEventBody.ROOT_PROCESS_ID_META_DATA), - addons, - identity); - addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE, metaData.get(UserTaskInstanceEventBody.UT_STATE_META_DATA)); - addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID, metaData.get(metaData.get(UserTaskInstanceEventBody.UT_ID_META_DATA))); + kogitoProcessInstanceId, + kogitoRootProcessInstanceId, + kogitoProcessId, + kogitoRootProcessId, + kogitoAddons, + kogitoIdentity); + setKogitoUserTaskInstanceId(kogitoUserTaskInstanceId); + setKogitoUserTaskInstanceState(kogitoUserTaskInstanceState); + setKogitoProcessInstanceVersion(kogitoProcessInstanceVersion); + setKogitoParentProcessInstanceId(kogitoParentProcessInstanceId); + setKogitoProcessInstanceState(kogitoProcessInstanceState); + setKogitoReferenceId(kogitoReferenceId); + setKogitoProcessType(kogitoProcessType); } - public String getKogitoUserTaskinstanceId() { - return kogitoUserTaskinstanceId; + public String getKogitoUserTaskInstanceId() { + return kogitoUserTaskInstanceId; } - public String getKogitoUserTaskinstanceState() { - return kogitoUserTaskinstanceState; + public String getKogitoUserTaskInstanceState() { + return kogitoUserTaskInstanceState; } - public void setKogitoUserTaskinstanceId(String kogitoUserTaskinstanceId) { - addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID, kogitoUserTaskinstanceId); + public void setKogitoUserTaskInstanceId(String kogitoUserTaskInstanceId) { + addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID, kogitoUserTaskInstanceId); } - public void setKogitoUserTaskinstanceState(String kogitoUserTaskinstanceState) { - addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE, kogitoUserTaskinstanceState); + public void setKogitoUserTaskInstanceState(String kogitoUserTaskInstanceState) { + addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE, kogitoUserTaskInstanceState); } @Override @@ -80,10 +104,10 @@ public void addExtensionAttribute(String name, Object value) { if (value != null) { switch (name) { case CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE: - this.kogitoUserTaskinstanceState = (String) value; + this.kogitoUserTaskInstanceState = (String) value; break; case CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID: - this.kogitoUserTaskinstanceId = (String) value; + this.kogitoUserTaskInstanceId = (String) value; break; } super.addExtensionAttribute(name, value); @@ -94,4 +118,5 @@ public void addExtensionAttribute(String name, Object value) { protected boolean isInternalAttribute(String name) { return INTERNAL_EXTENSION_ATTRIBUTES.contains(name) || super.isInternalAttribute(name); } + } diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDeadlineDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDeadlineDataEvent.java new file mode 100644 index 00000000000..fcd3e246e6f --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceDeadlineDataEvent.java @@ -0,0 +1,50 @@ +/* + * 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.event.usertask; + +import java.util.Map; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceDeadlineDataEvent extends UserTaskInstanceDataEvent { + + public UserTaskInstanceDeadlineDataEvent() { + } + + public UserTaskInstanceDeadlineDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceDeadlineEventBody body) { + super("UserTaskInstanceDeadlineDataEvent", + source, + body, + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA), + identity); + + } + +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceStateDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceStateDataEvent.java new file mode 100644 index 00000000000..00c6eb224f9 --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceStateDataEvent.java @@ -0,0 +1,50 @@ +/* + * 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.event.usertask; + +import java.util.Map; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceStateDataEvent extends UserTaskInstanceDataEvent { + + public UserTaskInstanceStateDataEvent() { + } + + public UserTaskInstanceStateDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceStateEventBody body) { + super("UserTaskInstanceStateDataEvent", + source, + body, + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA), + identity); + + } + +} diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceVariableDataEvent.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceVariableDataEvent.java new file mode 100644 index 00000000000..f86611a620a --- /dev/null +++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/usertask/UserTaskInstanceVariableDataEvent.java @@ -0,0 +1,50 @@ +/* + * 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.event.usertask; + +import java.util.Map; + +import org.kie.kogito.event.process.ProcessInstanceEventMetadata; + +public class UserTaskInstanceVariableDataEvent extends UserTaskInstanceDataEvent { + + public UserTaskInstanceVariableDataEvent() { + } + + public UserTaskInstanceVariableDataEvent(String source, String addons, String identity, Map metaData, UserTaskInstanceVariableEventBody body) { + super("UserTaskInstanceVariableDataEvent", + source, + body, + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_ID_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_STATE_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_VERSION_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PARENT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_INSTANCE_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.ROOT_PROCESS_ID_META_DATA), + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_INSTANCE_STATE_META_DATA), + addons, + (String) metaData.get(ProcessInstanceEventMetadata.PROCESS_TYPE_META_DATA), + (String) metaData.get(UserTaskInstanceEventMetadata.USER_TASK_INSTANCE_REFERENCE_ID_META_DATA), + identity); + + } + +} diff --git a/api/kogito-events-core/src/test/java/org/kie/kogito/event/cloudevents/utils/CloudEventUtilsTest.java b/api/kogito-events-core/src/test/java/org/kie/kogito/event/cloudevents/utils/CloudEventUtilsTest.java index d199a837769..162acd865d3 100644 --- a/api/kogito-events-core/src/test/java/org/kie/kogito/event/cloudevents/utils/CloudEventUtilsTest.java +++ b/api/kogito-events-core/src/test/java/org/kie/kogito/event/cloudevents/utils/CloudEventUtilsTest.java @@ -234,7 +234,6 @@ void testFromValue() throws IOException { .withExtension("pepe", "pepa"); DataEvent dataEvent = DataEventFactory.from(builder.build(), ced -> objectMapper.readTree(ced.toBytes())); JsonNode deserialized = CloudEventUtils.fromValue(dataEvent); - System.out.println(deserialized); JsonNode data = deserialized.get("data"); assertThat(data).isNotNull(); assertThat(data.get("name").asText()).isEqualTo("Javierito"); diff --git a/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/DataEventFactoryTest.java b/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/DataEventFactoryTest.java index c2dfe2baaa2..b25a592dd93 100644 --- a/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/DataEventFactoryTest.java +++ b/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/DataEventFactoryTest.java @@ -45,7 +45,6 @@ void testIsJacksonSerializable() throws JsonProcessingException, IOException { .withExtension("pepe", "pepa"); DataEvent dataEvent = DataEventFactory.from(builder.build(), ced -> objectMapper.readTree(ced.toBytes())); JsonNode deserialized = objectMapper.readTree(objectMapper.writeValueAsBytes(dataEvent.asCloudEvent(JsonCloudEventData::wrap))); - System.out.println(deserialized); JsonNode data = deserialized.get("data"); assertThat(data).isNotNull(); diff --git a/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/ProcessInstanceEventBatchTest.java b/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/ProcessInstanceEventBatchTest.java index f249d4552fa..4b117d04a5e 100644 --- a/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/ProcessInstanceEventBatchTest.java +++ b/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/ProcessInstanceEventBatchTest.java @@ -19,19 +19,11 @@ package org.kie.kogito.event.impl; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.MilestoneEventBody; -import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcessInstance; -import org.kie.kogito.process.flexible.ItemDescription.Status; -import org.kie.kogito.process.flexible.Milestone; -import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; -import static java.util.Collections.singleton; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; -import static org.kie.kogito.event.process.ProcessInstanceEventBody.PROCESS_ID_META_DATA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.kie.kogito.event.process.ProcessInstanceEventMetadata.PROCESS_ID_META_DATA; public class ProcessInstanceEventBatchTest { @@ -57,22 +49,4 @@ public void testServiceDefined() { assertThat(batch.extractRuntimeSource(singletonMap(PROCESS_ID_META_DATA, "demo.orders"))).isEqualTo("http://localhost:8080/orders"); } - @Test - public void testMilestones() { - ProcessInstanceEventBatch batch = new ProcessInstanceEventBatch(null, null); - - KogitoWorkflowProcessInstance pi = mock(KogitoWorkflowProcessInstance.class); - - when(pi.milestones()).thenReturn(null); - assertThat(batch.createMilestones(pi)).isEmpty(); - - when(pi.milestones()).thenReturn(emptyList()); - assertThat(batch.createMilestones(pi)).isEmpty(); - - Milestone milestone = Milestone.builder().withId("id").withName("name").withStatus(Status.AVAILABLE).build(); - when(pi.milestones()).thenReturn(singleton(milestone)); - - MilestoneEventBody milestoneEventBody = MilestoneEventBody.create().id("id").name("name").status(Status.AVAILABLE.name()).build(); - assertThat(batch.createMilestones(pi)).containsOnly(milestoneEventBody); - } } diff --git a/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/TestCloudEvent.java b/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/TestCloudEvent.java index 98f8a98aab5..8ad0fe00b5d 100644 --- a/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/TestCloudEvent.java +++ b/api/kogito-events-core/src/test/java/org/kie/kogito/event/impl/TestCloudEvent.java @@ -18,9 +18,9 @@ */ package org.kie.kogito.event.impl; -import org.kie.kogito.event.process.ProcessDataEvent; +import org.kie.kogito.event.process.ProcessInstanceDataEvent; -public class TestCloudEvent extends ProcessDataEvent { +public class TestCloudEvent extends ProcessInstanceDataEvent { public TestCloudEvent() { } diff --git a/api/kogito-events-core/src/test/java/org/kie/kogito/event/process/ProcessEventsTest.java b/api/kogito-events-core/src/test/java/org/kie/kogito/event/process/ProcessEventsTest.java index 86316cabe4c..0d4fb4fafa9 100644 --- a/api/kogito-events-core/src/test/java/org/kie/kogito/event/process/ProcessEventsTest.java +++ b/api/kogito-events-core/src/test/java/org/kie/kogito/event/process/ProcessEventsTest.java @@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.kie.kogito.event.AbstractDataEvent; import org.kie.kogito.event.cloudevents.CloudEventExtensionConstants; +import org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -94,7 +95,7 @@ class ProcessEventsTest { @Test void processInstanceDataEvent() throws Exception { - ProcessInstanceDataEvent event = new ProcessInstanceDataEvent(); + ProcessInstanceStateDataEvent event = new ProcessInstanceStateDataEvent(); setBaseEventValues(event, PROCESS_INSTANCE_EVENT_TYPE); setAdditionalExtensions(event); @@ -103,7 +104,7 @@ void processInstanceDataEvent() throws Exception { String json = OBJECT_MAPPER.writeValueAsString(event); assertExtensionsNotDuplicated(json, event.getExtensionNames()); - ProcessInstanceDataEvent deserializedEvent = OBJECT_MAPPER.readValue(json, ProcessInstanceDataEvent.class); + ProcessInstanceStateDataEvent deserializedEvent = OBJECT_MAPPER.readValue(json, ProcessInstanceStateDataEvent.class); assertBaseEventValues(deserializedEvent, PROCESS_INSTANCE_EVENT_TYPE); assertThat(deserializedEvent.getExtension(EXTENSION_1)).isEqualTo(EXTENSION_1_VALUE); @@ -113,7 +114,7 @@ void processInstanceDataEvent() throws Exception { @Test void userTaskInstanceDataEvent() throws Exception { - UserTaskInstanceDataEvent event = new UserTaskInstanceDataEvent(); + UserTaskInstanceStateDataEvent event = new UserTaskInstanceStateDataEvent(); setBaseEventValues(event, USER_TASK_INSTANCE_EVENT_TYPE); event.addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_ID, PROCESS_USER_TASK_INSTANCE_ID); event.addExtensionAttribute(CloudEventExtensionConstants.PROCESS_USER_TASK_INSTANCE_STATE, PROCESS_USER_TASK_INSTANCE_STATE); @@ -126,7 +127,7 @@ void userTaskInstanceDataEvent() throws Exception { String json = OBJECT_MAPPER.writeValueAsString(event); assertExtensionsNotDuplicated(json, event.getExtensionNames()); - UserTaskInstanceDataEvent deserializedEvent = OBJECT_MAPPER.readValue(json, UserTaskInstanceDataEvent.class); + UserTaskInstanceStateDataEvent deserializedEvent = OBJECT_MAPPER.readValue(json, UserTaskInstanceStateDataEvent.class); assertBaseEventValues(deserializedEvent, USER_TASK_INSTANCE_EVENT_TYPE); assertThat(deserializedEvent.getExtension(EXTENSION_1)).isEqualTo(EXTENSION_1_VALUE); assertThat(deserializedEvent.getExtension(EXTENSION_2)).isEqualTo(EXTENSION_2_VALUE); @@ -140,7 +141,7 @@ void userTaskInstanceDataEvent() throws Exception { @Test void variableInstanceDataEvent() throws Exception { - VariableInstanceDataEvent event = new VariableInstanceDataEvent(); + ProcessInstanceVariableDataEvent event = new ProcessInstanceVariableDataEvent(); setBaseEventValues(event, VARIABLE_INSTANCE_EVENT_TYPE); event.addExtensionAttribute(CloudEventExtensionConstants.KOGITO_VARIABLE_NAME, VARIABLE_NAME); setAdditionalExtensions(event); @@ -150,7 +151,7 @@ void variableInstanceDataEvent() throws Exception { String json = OBJECT_MAPPER.writeValueAsString(event); assertExtensionsNotDuplicated(json, event.getExtensionNames()); - VariableInstanceDataEvent deserializedEvent = OBJECT_MAPPER.readValue(json, VariableInstanceDataEvent.class); + ProcessInstanceVariableDataEvent deserializedEvent = OBJECT_MAPPER.readValue(json, ProcessInstanceVariableDataEvent.class); assertBaseEventValues(deserializedEvent, VARIABLE_INSTANCE_EVENT_TYPE); assertThat(deserializedEvent.getExtension(EXTENSION_1)).isEqualTo(EXTENSION_1_VALUE); assertThat(deserializedEvent.getExtension(EXTENSION_2)).isEqualTo(EXTENSION_2_VALUE); diff --git a/api/kogito-services/src/main/java/org/kie/kogito/services/registry/ProcessDefinitionEventRegistry.java b/api/kogito-services/src/main/java/org/kie/kogito/services/registry/ProcessDefinitionEventRegistry.java new file mode 100644 index 00000000000..768cccb7441 --- /dev/null +++ b/api/kogito-services/src/main/java/org/kie/kogito/services/registry/ProcessDefinitionEventRegistry.java @@ -0,0 +1,114 @@ +/* + * 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.services.registry; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.kie.kogito.Application; +import org.kie.kogito.event.EventBatch; +import org.kie.kogito.event.impl.ProcessEventBatch; +import org.kie.kogito.event.process.NodeDefinition; +import org.kie.kogito.event.process.ProcessDefinitionDataEvent; +import org.kie.kogito.event.process.ProcessDefinitionEventBody; +import org.kie.kogito.internal.utils.ConversionUtils; +import org.kie.kogito.process.Process; +import org.kie.kogito.process.Processes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toSet; + +public class ProcessDefinitionEventRegistry { + + private static final Logger LOGGER = LoggerFactory.getLogger(ProcessDefinitionEventRegistry.class); + + private Application app; + private String serviceUrl; + + public ProcessDefinitionEventRegistry(Application app, String serviceUrl) { + this.app = app; + this.serviceUrl = serviceUrl; + } + + public void register(Processes processes) { + EventBatch eventBatch = new ProcessEventBatch(); + processes.processIds().stream() + .map(processes::processById) + .map(mapProcessDefinition(app.config().addons().availableAddons(), serviceUrl)) + .forEach(process -> { + LOGGER.debug("Registering process definition with id: {}", process.getId()); + eventBatch.append(process); + }); + LOGGER.debug("Publishing all processes definitions"); + app.unitOfWorkManager().eventManager().publish(eventBatch); + } + + private Function, ProcessDefinitionDataEvent> mapProcessDefinition(Set addons, String endpoint) { + + return p -> { + Map metadata = Collections.emptyMap(); + if (p instanceof Supplier) { + org.kie.api.definition.process.Process processDefinition = ((Supplier) p).get(); + if (processDefinition != null) { + metadata = processDefinition.getMetaData(); + } + } + Set annotations = ((List) metadata.getOrDefault("annotations", emptyList())).stream().collect(toSet()); + String description = (String) metadata.get("Description"); + ProcessDefinitionDataEvent definitionDataEvent = new ProcessDefinitionDataEvent(ProcessDefinitionEventBody.builder() + .setId(p.id()) + .setName(p.name()) + .setVersion(p.version()) + .setType(p.type()) + .setAddons(addons) + .setEndpoint(getEndpoint(endpoint, p)) + .setNodes(getNodesDefinitions(p)) + .setAnnotations(annotations) + .setDescription(description) + .setMetadata(metadata) + .build()); + return definitionDataEvent; + }; + } + + private static String getEndpoint(String endpoint, Process p) { + //sanitize process path in case of fqdn org.acme.ProcessExample -> ProcessExample + String processPath = ConversionUtils.sanitizeToSimpleName(p.id()); + return endpoint + "/" + processPath; + } + + private List getNodesDefinitions(Process p) { + return p.findNodes(n -> true).stream() + .map(node -> NodeDefinition.builder() + .setId(String.valueOf(node.getId())) + .setName(node.getName()) + .setType(node.getClass().getSimpleName()) + .setUniqueId(node.getUniqueId()) + .setMetadata(node.getMetaData()) + .build()) + .collect(Collectors.toList()); + } +} diff --git a/api/kogito-services/src/main/java/org/kie/kogito/services/uow/CollectingUnitOfWork.java b/api/kogito-services/src/main/java/org/kie/kogito/services/uow/CollectingUnitOfWork.java index 4216f8c798f..bbbc1444297 100644 --- a/api/kogito-services/src/main/java/org/kie/kogito/services/uow/CollectingUnitOfWork.java +++ b/api/kogito-services/src/main/java/org/kie/kogito/services/uow/CollectingUnitOfWork.java @@ -43,6 +43,7 @@ public class CollectingUnitOfWork implements UnitOfWork { private boolean done; private final EventManager eventManager; + private EventBatch batch; public CollectingUnitOfWork(EventManager eventManager) { this.eventManager = eventManager; @@ -54,17 +55,17 @@ public void start() { if (collectedWork == null) { collectedWork = new LinkedHashSet<>(); } + batch = eventManager.newBatch(); } @Override public void end() { checkStarted(); - EventBatch batch = eventManager.newBatch(); for (WorkUnit work : sorted()) { - batch.append(work.data()); work.perform(); } + eventManager.publish(batch); done(); } @@ -72,9 +73,10 @@ public void end() { @Override public void abort() { checkStarted(); - for (WorkUnit work : sorted()) { + for (WorkUnit work : collectedWork) { work.abort(); } + batch = null; done(); } @@ -85,6 +87,7 @@ public void intercept(WorkUnit work) { if (work == null) { throw new NullPointerException("Work must be non null"); } + batch.append(work.data()); collectedWork.remove(work); collectedWork.add(work); } diff --git a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/FlowTest.java b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/FlowTest.java index fcde33257e9..83fa005825b 100755 --- a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/FlowTest.java +++ b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/FlowTest.java @@ -33,7 +33,7 @@ import org.jbpm.process.instance.InternalProcessRuntime; import org.jbpm.process.instance.context.variable.VariableScopeInstance; import org.jbpm.process.instance.impl.demo.SystemOutWorkItemHandler; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.test.util.NodeLeftCountDownProcessEventListener; import org.jbpm.workflow.instance.impl.NodeInstanceImpl; import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl; @@ -1352,7 +1352,7 @@ public void testLane() throws Exception { assertThat(KogitoWorkItem).isNotNull(); assertThat(KogitoWorkItem.getParameter("ActorId")).isEqualTo("john"); Map results = new HashMap<>(); - ((HumanTaskWorkItemImpl) KogitoWorkItem).setActualOwner("mary"); + ((InternalHumanTaskWorkItem) KogitoWorkItem).setActualOwner("mary"); kruntime.getKogitoWorkItemManager().completeWorkItem(KogitoWorkItem.getStringId(), results); kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human Task", diff --git a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StandaloneBPMNProcessTest.java b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StandaloneBPMNProcessTest.java index 1e9b9ddf60d..ab2759a265c 100755 --- a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StandaloneBPMNProcessTest.java +++ b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StandaloneBPMNProcessTest.java @@ -39,7 +39,7 @@ import org.jbpm.bpmn2.objects.TestWorkItemHandler; import org.jbpm.process.instance.impl.demo.DoNothingWorkItemHandler; import org.jbpm.process.instance.impl.demo.SystemOutWorkItemHandler; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.test.util.NodeLeftCountDownProcessEventListener; import org.jbpm.test.util.ProcessCompletedCountDownProcessEventListener; import org.junit.jupiter.api.Disabled; @@ -172,7 +172,7 @@ public void testLane() throws Exception { assertThat(workItem).isNotNull(); assertThat(workItem.getParameter("ActorId")).isEqualTo("john"); Map results = new HashMap<>(); - ((HumanTaskWorkItemImpl) workItem).setActualOwner("mary"); + ((InternalHumanTaskWorkItem) workItem).setActualOwner("mary"); kruntime.getKogitoWorkItemManager().completeWorkItem(workItem.getStringId(), results); kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human Task", workItemHandler); workItem = workItemHandler.getWorkItem(); diff --git a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StartEventTest.java b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StartEventTest.java index a90159f65ee..a26789a9dfb 100755 --- a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StartEventTest.java +++ b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/StartEventTest.java @@ -42,7 +42,7 @@ import org.kie.kogito.internal.process.event.DefaultKogitoProcessEventListener; import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; -import org.kie.kogito.process.workitems.impl.KogitoWorkItemImpl; +import org.kie.kogito.process.workitems.InternalKogitoWorkItem; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -319,7 +319,7 @@ public void afterProcessStarted(ProcessStartedEvent event) { assertThat(list).hasSize(1); KogitoWorkItem workItem = workItemHandler.getWorkItem(); - String processInstanceId = ((KogitoWorkItemImpl) workItem) + String processInstanceId = ((InternalKogitoWorkItem) workItem) .getProcessInstanceStringId(); KogitoProcessInstance processInstance = kruntime @@ -423,7 +423,7 @@ public void afterProcessStarted(ProcessStartedEvent event) { assertThat(list).hasSize(1); KogitoWorkItem workItem = workItemHandler.getWorkItem(); - String processInstanceId = ((KogitoWorkItemImpl) workItem) + String processInstanceId = ((InternalKogitoWorkItem) workItem) .getProcessInstanceStringId(); KogitoProcessInstance processInstance = kruntime diff --git a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/objects/TestWorkItemHandler.java b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/objects/TestWorkItemHandler.java index 82ee33cc429..48a5612d5a5 100755 --- a/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/objects/TestWorkItemHandler.java +++ b/jbpm/jbpm-bpmn2/src/test/java/org/jbpm/bpmn2/objects/TestWorkItemHandler.java @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.List; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.workitem.Active; import org.jbpm.process.instance.impl.workitem.Complete; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; @@ -40,7 +40,7 @@ public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manag workItems.add(workItem); if (workItem instanceof HumanTaskWorkItem) { - HumanTaskWorkItemImpl humanTaskWorkItem = (HumanTaskWorkItemImpl) workItem; + InternalHumanTaskWorkItem humanTaskWorkItem = (InternalHumanTaskWorkItem) workItem; humanTaskWorkItem.setPhaseId(Active.ID); humanTaskWorkItem.setPhaseStatus(Active.STATUS); diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ForEachNodeVisitor.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ForEachNodeVisitor.java index 7fe518fcba6..422c2dac03d 100644 --- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ForEachNodeVisitor.java +++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ForEachNodeVisitor.java @@ -96,10 +96,6 @@ public void visitNode(String factoryField, ForEachNode node, BlockStmt body, Var buildDataResolver(node.getOutputVariableType().getStringType()))); } - if (node.getExpressionLanguage() != null) { - body.addStatement(getFactoryMethod(getNodeId(node), "expressionLanguage", new StringLiteralExpr(node.getExpressionLanguage()))); - } - if (node.getCompletionAction() instanceof ExpressionSupplier) { body.addStatement(getFactoryMethod(getNodeId(node), "completionAction", ((ExpressionSupplier) node.getCompletionAction()).get(node, metadata))); } diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessVisitor.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessVisitor.java index d82cca9ded8..ec9b667b911 100644 --- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessVisitor.java +++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessVisitor.java @@ -149,6 +149,13 @@ public void visitProcess(WorkflowProcess process, MethodDeclaration processMetho visitVariableScope(FACTORY_FIELD_NAME, variableScope, body, visitedVariables, metadata.getProcessClassName()); visitSubVariableScopes(process.getNodes(), body, visitedVariables); + if (process instanceof org.jbpm.workflow.core.WorkflowProcess) { + org.jbpm.workflow.core.WorkflowProcess processImpl = (org.jbpm.workflow.core.WorkflowProcess) process; + if (processImpl.getExpressionLanguage() != null) { + body.addStatement(getFactoryMethod(FACTORY_FIELD_NAME, "expressionLanguage", new StringLiteralExpr(processImpl.getExpressionLanguage()))); + } + } + visitInterfaces(process.getNodes()); metadata.setDynamic(((org.jbpm.workflow.core.WorkflowProcess) process).isDynamic()); diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/ExpressionUtils.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/ExpressionUtils.java index 163e6d005f9..f8103343261 100644 --- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/ExpressionUtils.java +++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/ExpressionUtils.java @@ -108,7 +108,7 @@ public static Expression getLiteralExpr(Object object) { } else if (object instanceof Character) { return new CharLiteralExpr(((Character) object)); } else if (object instanceof Long) { - return new LongLiteralExpr(object.toString()); + return new LongLiteralExpr(object + "L"); } else if (object instanceof Integer || object instanceof Short) { return new IntegerLiteralExpr(object.toString()); } else if (object instanceof BigInteger) { diff --git a/jbpm/jbpm-flow-builder/src/test/java/org/jbpm/integrationtests/ProcessHumanTaskTest.java b/jbpm/jbpm-flow-builder/src/test/java/org/jbpm/integrationtests/ProcessHumanTaskTest.java index 77fcab84f6f..3df5fb4d8c3 100755 --- a/jbpm/jbpm-flow-builder/src/test/java/org/jbpm/integrationtests/ProcessHumanTaskTest.java +++ b/jbpm/jbpm-flow-builder/src/test/java/org/jbpm/integrationtests/ProcessHumanTaskTest.java @@ -26,7 +26,7 @@ import org.drools.io.ReaderResource; import org.jbpm.integrationtests.handler.TestWorkItemHandler; import org.jbpm.process.instance.ProcessInstance; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.test.util.AbstractBaseTest; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -170,7 +170,7 @@ public void testSwimlane() { assertThat(workItem.getParameter("TaskName")).isEqualTo("Do something"); assertThat(workItem.getParameter("ActorId")).isEqualTo("John Doe"); Map results = new HashMap(); - ((HumanTaskWorkItemImpl) workItem).setActualOwner("Jane Doe"); + ((InternalHumanTaskWorkItem) workItem).setActualOwner("Jane Doe"); kruntime.getKogitoWorkItemManager().completeWorkItem(workItem.getStringId(), results); workItem = handler.getWorkItem(); assertThat(workItem).isNotNull(); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntime.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntime.java index 3c521de1daa..501b3bfccdc 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntime.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntime.java @@ -178,8 +178,8 @@ private KogitoProcessInstance createProcessInstance(Process process, Correlation runtimeContext.startOperation(); org.jbpm.process.instance.ProcessInstance pi = runtimeContext.createProcessInstance(process, correlationKey); pi.setKnowledgeRuntime(knowledgeRuntime); - runtimeContext.setupParameters(pi, parameters); processInstanceManager.addProcessInstance(pi); + runtimeContext.setupParameters(pi, parameters); return pi; } finally { runtimeContext.endOperation(); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntimeContext.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntimeContext.java index ad113d1dfa3..29749236421 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntimeContext.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightProcessRuntimeContext.java @@ -100,8 +100,7 @@ public void setupParameters(ProcessInstance processInstance, Map for (Map.Entry entry : parameters.entrySet()) { if (entry.getValue() != null) { variableScope.validateVariable(process.getName(), entry.getKey(), entry.getValue()); - //Use internalSetVariable in order to avoid publishing variable change events - variableScopeInstance.internalSetVariable(entry.getKey(), entry.getValue()); + variableScopeInstance.setVariable(entry.getKey(), entry.getValue()); } } } else { diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java index cc45b85285a..67cf635ebb8 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -71,7 +70,6 @@ public LightWorkItemManager(ProcessInstanceManager processInstanceManager, Signa @Override public void internalExecuteWorkItem(InternalKogitoWorkItem workItem) { - ((KogitoWorkItemImpl) workItem).setId(UUID.randomUUID().toString()); internalAddWorkItem(workItem); KogitoWorkItemHandler handler = this.workItemHandlers.get(workItem.getName()); if (handler != null) { @@ -94,7 +92,7 @@ public void internalAddWorkItem(InternalKogitoWorkItem workItem) { @Override public void internalAbortWorkItem(String id) { - KogitoWorkItemImpl workItem = (KogitoWorkItemImpl) workItems.get(id); + InternalKogitoWorkItem workItem = workItems.get(id); // work item may have been aborted if (workItem != null) { workItem.setCompleteDate(new Date()); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/context/variable/VariableScopeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/context/variable/VariableScopeInstance.java index a719eadff3e..7c1c5189865 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/context/variable/VariableScopeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/context/variable/VariableScopeInstance.java @@ -20,17 +20,13 @@ import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; -import org.drools.core.common.InternalKnowledgeRuntime; import org.jbpm.process.core.context.variable.Variable; import org.jbpm.process.core.context.variable.VariableScope; -import org.jbpm.process.core.datatype.impl.coverter.CloneHelper; import org.jbpm.process.instance.ContextInstanceContainer; import org.jbpm.process.instance.InternalProcessRuntime; -import org.jbpm.process.instance.ProcessInstance; import org.jbpm.process.instance.context.AbstractContextInstance; import org.jbpm.workflow.core.Node; import org.jbpm.workflow.instance.node.CompositeContextNodeInstance; @@ -92,42 +88,39 @@ public void setVariable(String name, Object value) { public void setVariable(KogitoNodeInstance nodeInstance, String name, Object value) { Objects.requireNonNull(name, "The name of a variable may not be null!"); // check if variable that is being set is readonly and has already been set - VariableScope scope = getVariableScope(); - ProcessInstance pi = getProcessInstance(); Object oldValue = getVariable(name); - if (oldValue != null && scope.isReadOnly(name)) { - throw new VariableViolationException(pi.getStringId(), name, "Variable '" + name + "' is already set and is marked as read only"); + if (oldValue != null && getVariableScope().isReadOnly(name)) { + throw new VariableViolationException(getProcessInstance().getStringId(), name, "Variable '" + name + "' is already set and is marked as read only"); } // ignore similar value if (ignoreChange(oldValue, value)) { return; } - List tags = scope.tags(name); - Object newValue = value; - InternalKnowledgeRuntime runtime = pi.getKnowledgeRuntime(); - - if (runtime != null) { - if (!tags.contains(Variable.INTERNAL_TAG)) { - newValue = CloneHelper.get().clone(value); - } + final Object clonedValue = getProcessInstance().getKnowledgeRuntime() != null ? clone(name, value) : null; + if (clonedValue != null) { getProcessEventSupport().fireBeforeVariableChanged( (variableIdPrefix == null ? "" : variableIdPrefix + ":") + name, (variableInstanceIdPrefix == null ? "" : variableInstanceIdPrefix + ":") + name, - oldValue, newValue, tags, pi, + oldValue, clonedValue, getVariableScope().tags(name), getProcessInstance(), nodeInstance, - runtime); + getProcessInstance().getKnowledgeRuntime()); } internalSetVariable(name, value); - if (runtime != null) { + if (clonedValue != null) { getProcessEventSupport().fireAfterVariableChanged( (variableIdPrefix == null ? "" : variableIdPrefix + ":") + name, (variableInstanceIdPrefix == null ? "" : variableInstanceIdPrefix + ":") + name, - oldValue, newValue, tags, pi, + oldValue, clonedValue, getVariableScope().tags(name), getProcessInstance(), nodeInstance, - runtime); + getProcessInstance().getKnowledgeRuntime()); } } + private Object clone(String name, Object newValue) { + Variable variable = getVariableScope().findVariable(name); + return variable != null ? variable.getType().clone(newValue) : newValue; + } + private boolean ignoreChange(Object oldValue, Object newValue) { if (newValue instanceof KogitoObjectListenerAware) { return Objects.equals(oldValue, newValue) || (oldValue == null && ((KogitoObjectListenerAware) newValue).isEmpty()); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/KogitoProcessEventSupportImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/KogitoProcessEventSupportImpl.java index 41d29521dc7..2a87fcd4c95 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/KogitoProcessEventSupportImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/KogitoProcessEventSupportImpl.java @@ -21,9 +21,11 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; import org.kie.api.event.process.MessageEvent; import org.kie.api.event.process.ProcessCompletedEvent; import org.kie.api.event.process.ProcessNodeLeftEvent; @@ -32,17 +34,20 @@ import org.kie.api.event.process.ProcessVariableChangedEvent; import org.kie.api.event.process.SLAViolatedEvent; import org.kie.api.event.process.SignalEvent; +import org.kie.api.event.usertask.UserTaskDeadlineEvent; +import org.kie.api.event.usertask.UserTaskDeadlineEvent.DeadlineType; +import org.kie.api.event.usertask.UserTaskVariableEvent.VariableEventType; import org.kie.api.runtime.KieRuntime; import org.kie.internal.runtime.Closeable; import org.kie.kogito.auth.IdentityProvider; -import org.kie.kogito.internal.process.event.HumanTaskDeadlineEvent; -import org.kie.kogito.internal.process.event.HumanTaskDeadlineEvent.DeadlineType; import org.kie.kogito.internal.process.event.KogitoProcessEventListener; import org.kie.kogito.internal.process.event.KogitoProcessEventSupport; import org.kie.kogito.internal.process.event.ProcessWorkItemTransitionEvent; import org.kie.kogito.internal.process.runtime.KogitoNodeInstance; import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; +import org.kie.kogito.process.workitem.Attachment; +import org.kie.kogito.process.workitem.Comment; import org.kie.kogito.process.workitem.HumanTaskWorkItem; import org.kie.kogito.process.workitem.Transition; @@ -205,33 +210,161 @@ public void fireOnMessage(final KogitoProcessInstance instance, KogitoNodeInstan notifyAllListeners(l -> l.onMessage(event)); } + // users tasks events @Override - public void fireOnTaskNotStartedDeadline(KogitoProcessInstance instance, + public void fireOnUserTaskNotStartedDeadline(KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, HumanTaskWorkItem workItem, Map notification, KieRuntime kruntime) { - fireTaskNotification(instance, workItem, notification, DeadlineType.Started, kruntime); + fireUserTaskNotification(instance, nodeInstance, workItem, notification, DeadlineType.Started, kruntime); } @Override - public void fireOnTaskNotCompletedDeadline(KogitoProcessInstance instance, + public void fireOnUserTaskNotCompletedDeadline(KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, HumanTaskWorkItem workItem, Map notification, KieRuntime kruntime) { - fireTaskNotification(instance, workItem, notification, DeadlineType.Completed, kruntime); + fireUserTaskNotification(instance, nodeInstance, workItem, notification, DeadlineType.Completed, kruntime); } - private void fireTaskNotification(KogitoProcessInstance instance, + private void fireUserTaskNotification(KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, HumanTaskWorkItem workItem, Map notification, DeadlineType type, KieRuntime kruntime) { - final HumanTaskDeadlineEvent event = new HumanTaskDeadlineEventImpl(instance, workItem, notification, type, kruntime, identityProvider.getName()); - notifyAllListeners(l -> l.onHumanTaskDeadline(event)); + UserTaskDeadlineEvent event = new UserTaskDeadlineEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, workItem, notification, type, kruntime, identityProvider.getName()); + notifyAllListeners(l -> l.onUserTaskDeadline(event)); + } + + @Override + public void fireOneUserTaskStateChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + String oldStatus, String newStatus) { + UserTaskStateEventImpl event = new UserTaskStateEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setOldStatus(oldStatus); + event.setNewStatus(newStatus); + notifyAllListeners(l -> l.onUserTaskState(event)); + } + + @Override + public void fireOnUserTaskAssignmentChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + AssignmentType assignmentType, + Set oldUsersId, Set newUsersId) { + UserTaskAssignmentEventImpl event = new UserTaskAssignmentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setAssignmentType(assignmentType.name()); + event.setOldUsersId(oldUsersId); + event.setNewUsersId(newUsersId); + notifyAllListeners(l -> l.onUserTaskAssignment(event)); + } + + @Override + public void fireOnUserTaskInputVariableChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + String variableName, Object newValue, Object oldValue) { + UserTaskVariableEventImpl event = new UserTaskVariableEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setVariableName(variableName); + event.setOldValue(oldValue); + event.setNewValue(newValue); + event.setVariableType(VariableEventType.INPUT); + notifyAllListeners(l -> l.onUserTaskInputVariable(event)); + } + + @Override + public void fireOnUserTaskOutputVariableChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + String variableName, Object newValue, Object oldValue) { + UserTaskVariableEventImpl event = new UserTaskVariableEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setVariableName(variableName); + event.setOldValue(oldValue); + event.setNewValue(newValue); + event.setVariableType(VariableEventType.OUTPUT); + notifyAllListeners(l -> l.onUserTaskOutputVariable(event)); + } + + @Override + public void fireOnUserTaskAttachmentAdded( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Attachment addedAttachment) { + + UserTaskAttachmentEventImpl event = new UserTaskAttachmentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setNewAttachment(addedAttachment); + notifyAllListeners(l -> l.onUserTaskAttachmentAdded(event)); + } + + @Override + public void fireOnUserTaskAttachmentChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Attachment oldAttachment, Attachment newAttachment) { + UserTaskAttachmentEventImpl event = new UserTaskAttachmentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setOldAttachment(oldAttachment); + event.setNewAttachment(newAttachment); + notifyAllListeners(l -> l.onUserTaskAttachmentChange(event)); + } + + @Override + public void fireOnUserTaskAttachmentDeleted( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Attachment deletedAttachment) { + UserTaskAttachmentEventImpl event = new UserTaskAttachmentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setOldAttachment(deletedAttachment); + notifyAllListeners(l -> l.onUserTaskAttachmentDeleted(event)); + } + + @Override + public void fireOnUserTaskCommentAdded( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Comment addedComment) { + UserTaskCommentEventImpl event = new UserTaskCommentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setNewComment(addedComment); + notifyAllListeners(l -> l.onUserTaskCommentAdded(event)); + } + + @Override + public void fireOnUserTaskCommentChange( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Comment oldComment, Comment newComment) { + UserTaskCommentEventImpl event = new UserTaskCommentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setOldComment(oldComment); + event.setNewComment(newComment); + notifyAllListeners(l -> l.onUserTaskCommentChange(event)); + } + + @Override + public void fireOnUserTaskCommentDeleted( + KogitoProcessInstance instance, + KogitoNodeInstance nodeInstance, + KieRuntime kruntime, + Comment deletedComment) { + UserTaskCommentEventImpl event = new UserTaskCommentEventImpl(instance, (HumanTaskNodeInstance) nodeInstance, kruntime, identityProvider.getName()); + event.setOldComment(deletedComment); + notifyAllListeners(l -> l.onUserTaskCommentDeleted(event)); } @Override public void reset() { this.clear(); } + } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskAssignmentEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskAssignmentEventImpl.java new file mode 100644 index 00000000000..f2fb0a7a33c --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskAssignmentEventImpl.java @@ -0,0 +1,72 @@ +/* + * 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.jbpm.process.instance.event; + +import java.util.Set; + +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskAssignmentEvent; +import org.kie.api.runtime.KieRuntime; +import org.kie.api.runtime.process.ProcessInstance; + +public class UserTaskAssignmentEventImpl extends UserTaskEventImpl implements UserTaskAssignmentEvent { + + private static final long serialVersionUID = 1964525156416025043L; + private String assignmentType; + private String[] oldUsersId; + private String[] newUsersId; + + public UserTaskAssignmentEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime, String identity) { + super(instance, nodeInstance, kruntime, identity); + } + + @Override + public String getUserTaskId() { + return getHumanTaskNodeInstance().getWorkItemId(); + } + + public void setAssignmentType(String name) { + this.assignmentType = name; + + } + + public void setOldUsersId(Set oldUsersId) { + this.oldUsersId = oldUsersId.toArray(String[]::new); + + } + + public void setNewUsersId(Set newUsersId) { + this.newUsersId = newUsersId.toArray(String[]::new); + } + + @Override + public String getAssignmentType() { + return assignmentType; + } + + @Override + public String[] getOldUsersId() { + return oldUsersId; + } + + @Override + public String[] getNewUsersId() { + return newUsersId; + } +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskAttachmentEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskAttachmentEventImpl.java new file mode 100644 index 00000000000..34d4f699627 --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskAttachmentEventImpl.java @@ -0,0 +1,92 @@ +/* + * 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.jbpm.process.instance.event; + +import java.net.URI; +import java.util.Date; + +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskAttachmentEvent; +import org.kie.api.runtime.KieRuntime; +import org.kie.api.runtime.process.ProcessInstance; +import org.kie.kogito.process.workitem.Attachment; + +public class UserTaskAttachmentEventImpl extends UserTaskEventImpl implements UserTaskAttachmentEvent { + + private static final long serialVersionUID = 3956348350804141924L; + private Attachment oldAttachment; + private Attachment newAttachment; + + public UserTaskAttachmentEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime, String user) { + super(instance, nodeInstance, kruntime, user); + } + + public void setOldAttachment(Attachment oldAttachment) { + this.oldAttachment = oldAttachment; + } + + public void setNewAttachment(Attachment newAttachment) { + this.newAttachment = newAttachment; + } + + @Override + public org.kie.api.event.usertask.Attachment getOldAttachment() { + return wrap(oldAttachment); + } + + @Override + public org.kie.api.event.usertask.Attachment getNewAttachment() { + return wrap(newAttachment); + } + + private org.kie.api.event.usertask.Attachment wrap(Attachment attachment) { + if (attachment == null) { + return null; + } + return new org.kie.api.event.usertask.Attachment() { + + @Override + public String getAttachmentId() { + return attachment.getId(); + } + + @Override + public String getAttachmentName() { + return attachment.getName(); + } + + @Override + public URI getAttachmentURI() { + return attachment.getContent(); + } + + @Override + public String getUpdatedBy() { + return attachment.getUpdatedBy(); + } + + @Override + public Date getUpdatedAt() { + return attachment.getUpdatedAt(); + } + + }; + } +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskCommentEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskCommentEventImpl.java new file mode 100644 index 00000000000..4bf5b512f60 --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskCommentEventImpl.java @@ -0,0 +1,92 @@ +/* + * 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.jbpm.process.instance.event; + +import java.util.Date; + +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskCommentEvent; +import org.kie.api.runtime.KieRuntime; +import org.kie.api.runtime.process.ProcessInstance; +import org.kie.kogito.process.workitem.Comment; + +public class UserTaskCommentEventImpl extends UserTaskEventImpl implements UserTaskCommentEvent { + + private static final long serialVersionUID = -7962827076724999755L; + private Comment oldComment; + private Comment newComment; + + public UserTaskCommentEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime, String user) { + super(instance, nodeInstance, kruntime, user); + } + + @Override + public String getUserTaskId() { + return getHumanTaskNodeInstance().getWorkItemId(); + } + + public void setOldComment(Comment oldComment) { + this.oldComment = oldComment; + } + + public void setNewComment(Comment newComment) { + this.newComment = newComment; + } + + @Override + public org.kie.api.event.usertask.Comment getNewComment() { + return wrap(newComment); + } + + @Override + public org.kie.api.event.usertask.Comment getOldComment() { + return wrap(oldComment); + } + + private org.kie.api.event.usertask.Comment wrap(Comment comment) { + if (comment == null) { + return null; + } + + return new org.kie.api.event.usertask.Comment() { + + @Override + public String getCommentId() { + return comment.getId(); + } + + @Override + public String getCommentContent() { + return comment.getContent(); + } + + @Override + public String getUpdatedBy() { + return comment.getUpdatedBy(); + } + + @Override + public Date getUpdatedAt() { + return comment.getUpdatedAt(); + } + + }; + } +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/HumanTaskDeadlineEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskDeadlineEventImpl.java similarity index 80% rename from jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/HumanTaskDeadlineEventImpl.java rename to jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskDeadlineEventImpl.java index c99834c7376..c660f92498a 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/HumanTaskDeadlineEventImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskDeadlineEventImpl.java @@ -20,32 +20,27 @@ import java.util.Map; +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskDeadlineEvent; import org.kie.api.runtime.KieRuntime; import org.kie.api.runtime.process.ProcessInstance; -import org.kie.kogito.internal.process.event.HumanTaskDeadlineEvent; import org.kie.kogito.process.workitem.HumanTaskWorkItem; -public class HumanTaskDeadlineEventImpl extends ProcessEvent - implements HumanTaskDeadlineEvent { +public class UserTaskDeadlineEventImpl extends UserTaskEventImpl implements UserTaskDeadlineEvent { private static final long serialVersionUID = 510l; private HumanTaskWorkItem workItem; private Map notification; private DeadlineType type; - public HumanTaskDeadlineEventImpl(ProcessInstance instance, HumanTaskWorkItem workItem, + public UserTaskDeadlineEventImpl(ProcessInstance instance, HumanTaskNodeInstance humanTaskNodeInstance, HumanTaskWorkItem workItem, Map notification, DeadlineType type, KieRuntime kruntime, String identity) { - super(instance, kruntime, identity); + super(instance, humanTaskNodeInstance, kruntime, identity); this.workItem = workItem; this.notification = notification; this.type = type; } - @Override - public HumanTaskWorkItem getWorkItem() { - return workItem; - } - @Override public Map getNotification() { return notification; diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskEventImpl.java new file mode 100644 index 00000000000..8bdbb36f42f --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskEventImpl.java @@ -0,0 +1,96 @@ +/* + * 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.jbpm.process.instance.event; + +import java.util.Date; +import java.util.EventObject; + +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskEvent; +import org.kie.api.runtime.KieRuntime; +import org.kie.api.runtime.process.ProcessInstance; + +public class UserTaskEventImpl extends EventObject implements UserTaskEvent { + + private static final long serialVersionUID = 510l; + + private final KieRuntime kruntime; + private final Date eventDate; + private final String eventUser; + + private HumanTaskNodeInstance humanTaskNodeInstance; + + public UserTaskEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime) { + this(instance, nodeInstance, kruntime, null); + } + + public UserTaskEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime, String user) { + super(instance); + this.humanTaskNodeInstance = nodeInstance; + this.kruntime = kruntime; + this.eventDate = new Date(); + this.eventUser = user; + } + + public ProcessInstance getProcessInstance() { + return (ProcessInstance) getSource(); + } + + @Override + public HumanTaskNodeInstance getNodeInstance() { + return humanTaskNodeInstance; + } + + @Override + public InternalHumanTaskWorkItem getWorkItem() { + return humanTaskNodeInstance.getWorkItem(); + } + + @Override + public String getUserTaskId() { + return getWorkItem().getStringId(); + } + + @Override + public KieRuntime getKieRuntime() { + return kruntime; + } + + public HumanTaskNodeInstance getHumanTaskNodeInstance() { + return humanTaskNodeInstance; + } + + @Override + public Date getEventDate() { + return this.eventDate; + } + + @Override + public String getEventUser() { + return eventUser; + } + + @Override + public String getUserTaskDefinitionId() { + return getWorkItem().getStringId(); + } + +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskStateEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskStateEventImpl.java new file mode 100644 index 00000000000..b2d82962cc5 --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskStateEventImpl.java @@ -0,0 +1,58 @@ +/* + * 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.jbpm.process.instance.event; + +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskStateEvent; +import org.kie.api.runtime.KieRuntime; +import org.kie.api.runtime.process.ProcessInstance; + +public class UserTaskStateEventImpl extends UserTaskEventImpl implements UserTaskStateEvent { + + private static final long serialVersionUID = 4556236095420836309L; + private String oldStatus; + private String newStatus; + + public UserTaskStateEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime, String identity) { + super(instance, nodeInstance, kruntime, identity); + } + + @Override + public String getUserTaskDefinitionId() { + return getHumanTaskNodeInstance().getNodeDefinitionId(); + } + + public void setOldStatus(String oldStatus) { + this.oldStatus = oldStatus; + + } + + public void setNewStatus(String newStatus) { + this.newStatus = newStatus; + + } + + public String getNewStatus() { + return newStatus; + } + + public String getOldStatus() { + return oldStatus; + } +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskVariableEventImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskVariableEventImpl.java new file mode 100644 index 00000000000..c833b187dd1 --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/event/UserTaskVariableEventImpl.java @@ -0,0 +1,80 @@ +/* + * 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.jbpm.process.instance.event; + +import org.jbpm.workflow.instance.node.HumanTaskNodeInstance; +import org.kie.api.event.usertask.UserTaskVariableEvent; +import org.kie.api.runtime.KieRuntime; +import org.kie.api.runtime.process.ProcessInstance; + +public class UserTaskVariableEventImpl extends UserTaskEventImpl implements UserTaskVariableEvent { + + private static final long serialVersionUID = -1160081990418929010L; + private String variableName; + private Object oldValue; + private Object newValue; + private VariableEventType variableType; + + public UserTaskVariableEventImpl(ProcessInstance instance, HumanTaskNodeInstance nodeInstance, KieRuntime kruntime, String identity) { + super(instance, nodeInstance, kruntime, identity); + } + + public void setVariableName(String variableName) { + this.variableName = variableName; + } + + public void setOldValue(Object oldValue) { + this.oldValue = oldValue; + } + + public void setNewValue(Object newValue) { + this.newValue = newValue; + } + + @Override + public String getVariableName() { + return variableName; + } + + @Override + public Object getOldValue() { + return oldValue; + } + + @Override + public Object getNewValue() { + return newValue; + } + + public void setVariableType(VariableEventType variableType) { + this.variableType = variableType; + } + + @Override + public VariableEventType getVariableType() { + return variableType; + } + + @Override + public String toString() { + return "UserTaskVariableEventImpl [variableName=" + variableName + ", oldValue=" + oldValue + ", newValue=" + newValue + ", variableType=" + variableType + "]"; + } + +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java index 0dc62c8ddd8..b78c644f7a2 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/ProcessInstanceImpl.java @@ -62,6 +62,8 @@ public abstract class ProcessInstanceImpl implements ProcessInstance, private Map> headers; + private String processVersion; + @Override public String getId() { return this.id; @@ -112,9 +114,15 @@ public Process getProcess() { @Override public void setProcess(final Process process) { this.processId = process.getId(); + this.processVersion = process.getVersion(); this.process = process; } + @Override + public String getProcessVersion() { + return processVersion; + } + @Override public String getProcessId() { return processId; diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/CancelNodeInstanceAction.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/CancelNodeInstanceAction.java index 66c70365a42..f078990abf4 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/CancelNodeInstanceAction.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/CancelNodeInstanceAction.java @@ -30,6 +30,6 @@ public CancelNodeInstanceAction(String attachedToNodeId) { @Override protected void execute(NodeInstance nodeInstance) { - ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel(); + ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel(org.jbpm.workflow.instance.NodeInstance.CancelType.SKIPPED); } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/HandleMessageAction.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/HandleMessageAction.java index a622f1feaee..8a08420e2bb 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/HandleMessageAction.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/HandleMessageAction.java @@ -20,6 +20,7 @@ import java.io.Serializable; import java.util.Map; +import java.util.UUID; import org.jbpm.process.instance.impl.Action; import org.jbpm.ruleflow.core.Metadata; @@ -44,6 +45,7 @@ public HandleMessageAction(String messageType, String variableName) { @Override public void execute(KogitoProcessContext context) throws Exception { KogitoWorkItemImpl workItem = new KogitoWorkItemImpl(); + workItem.setId(UUID.randomUUID().toString()); workItem.setName("Send Task"); workItem.setNodeInstanceId((context.getNodeInstance()).getStringId()); workItem.setProcessInstanceId((context.getProcessInstance()).getStringId()); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/SignalProcessInstanceAction.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/SignalProcessInstanceAction.java index 6bcaa023581..fe693e1cd76 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/SignalProcessInstanceAction.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/actions/SignalProcessInstanceAction.java @@ -21,6 +21,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import java.util.function.Function; import org.jbpm.process.instance.impl.Action; @@ -107,6 +108,7 @@ public void execute(KogitoProcessContext context) throws Exception { context.getProcessInstance().signalEvent(signalName, signal); } else if (EXTERNAL_SCOPE.equals(scope)) { KogitoWorkItemImpl workItem = new KogitoWorkItemImpl(); + workItem.setId(UUID.randomUUID().toString()); workItem.setName("External Send Task"); workItem.setNodeInstanceId(context.getNodeInstance().getStringId()); workItem.setProcessInstanceId(context.getProcessInstance().getStringId()); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/BaseHumanTaskLifeCycle.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/BaseHumanTaskLifeCycle.java index f3c5e6084f4..da143b94bf4 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/BaseHumanTaskLifeCycle.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/BaseHumanTaskLifeCycle.java @@ -98,7 +98,7 @@ public Collection phases() { public Map transitionTo(KogitoWorkItem workItem, KogitoWorkItemManager manager, Transition> transition) { logger.debug("Transition method invoked for work item {} to transition to {}, currently in phase {} and status {}", workItem.getStringId(), transition.phase(), workItem.getPhaseId(), workItem.getPhaseStatus()); - HumanTaskWorkItemImpl humanTaskWorkItem = (HumanTaskWorkItemImpl) workItem; + InternalHumanTaskWorkItem humanTaskWorkItem = (InternalHumanTaskWorkItem) workItem; LifeCyclePhase targetPhase = phases.get(transition.phase()); if (targetPhase == null) { @@ -123,7 +123,7 @@ public Map transitionTo(KogitoWorkItem workItem, KogitoWorkItemM targetPhase.apply(humanTaskWorkItem, transition); if (transition.data() != null) { logger.debug("Updating data for phase {} and work item {}", targetPhase.id(), humanTaskWorkItem.getStringId()); - humanTaskWorkItem.getResults().putAll(transition.data()); + humanTaskWorkItem.setResults(transition.data()); } logger.debug("Transition for work item {} to {} done, currently in phase {} and status {}", workItem.getStringId(), transition.phase(), workItem.getPhaseId(), workItem.getPhaseStatus()); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskHelper.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskHelper.java index 866f45bd049..7647ab7af2f 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskHelper.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskHelper.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.UUID; +import org.jbpm.workflow.instance.NodeInstance; import org.jbpm.workflow.instance.node.WorkItemNodeInstance; import org.kie.kogito.MapOutput; import org.kie.kogito.internal.process.runtime.KogitoNodeInstance; @@ -42,53 +43,73 @@ public class HumanTaskHelper { private HumanTaskHelper() { } - public static HumanTaskWorkItemImpl asHumanTask(KogitoWorkItem item) { - if (item instanceof HumanTaskWorkItemImpl) { - return (HumanTaskWorkItemImpl) item; + public static InternalHumanTaskWorkItem decorate(NodeInstance nodeInstance, InternalHumanTaskWorkItem delegate) { + return new HumanTaskWorkItemDecoratorImpl(nodeInstance, delegate); + } + + public static InternalHumanTaskWorkItem asHumanTask(KogitoWorkItem item) { + if (item instanceof InternalHumanTaskWorkItem) { + return (InternalHumanTaskWorkItem) item; } else { throw new IllegalArgumentException("Work item " + item.getStringId() + " is not a human task"); } } public static Comment addComment(KogitoWorkItem item, String commentInfo, String user) { - HumanTaskWorkItemImpl humanTask = asHumanTask(item); + InternalHumanTaskWorkItem humanTask = asHumanTask(item); String id = getNewId(); Comment comment = buildComment(id, commentInfo, user); - humanTask.getComments().put(id, comment); + humanTask.setComment(id, comment); return comment; } public static Attachment addAttachment(KogitoWorkItem item, AttachmentInfo attachmentInfo, String user) { - HumanTaskWorkItemImpl humanTask = asHumanTask(item); + InternalHumanTaskWorkItem humanTask = asHumanTask(item); String id = getNewId(); Attachment attachment = buildAttachment(id, attachmentInfo, user); - humanTask.getAttachments().put(id, attachment); + humanTask.setAttachment(id, attachment); return attachment; } public static Comment updateComment(KogitoWorkItem item, String id, String commentInfo, String user) { - Comment comment = asHumanTask(item).getComments().get(id); - if (comment == null) { - throw new IllegalArgumentException("Comment " + id + " does not exist"); - } - if (!comment.getUpdatedBy().equals(user)) { - throw new IllegalArgumentException("User " + user + " did not create the comment, cannot modify it"); + try { + InternalHumanTaskWorkItem humanTask = asHumanTask(item); + Comment comment = humanTask.getComments().get(id); + if (comment == null) { + throw new IllegalArgumentException("Comment " + id + " does not exist"); + } + if (!comment.getUpdatedBy().equals(user)) { + throw new IllegalArgumentException("User " + user + " did not create the comment, cannot modify it"); + } + comment = comment.clone(); + humanTask.setComment(id, fillTaskMetaEntity(comment, commentInfo)); + return comment; + } catch (CloneNotSupportedException e) { + throw new IllegalArgumentException("Attachment could not be modified", e); } - return fillTaskMetaEntity(comment, commentInfo); } public static Attachment updateAttachment(KogitoWorkItem item, String id, AttachmentInfo attachmentInfo, String user) { - Attachment attachment = asHumanTask(item).getAttachments().get(id); - if (attachment == null) { - throw new IllegalArgumentException("Attachment " + id + " does not exist"); + try { + InternalHumanTaskWorkItem humanTask = asHumanTask(item); + Attachment attachment = humanTask.getAttachments().get(id); + if (attachment == null) { + throw new IllegalArgumentException("Attachment " + id + " does not exist"); + } + if (!attachment.getUpdatedBy().equals(user)) { + throw new IllegalArgumentException("User " + user + " did not create the attachment, cannot modify it"); + } + + attachment = attachment.clone(); + humanTask.setAttachment(id, setAttachmentName(fillTaskMetaEntity(attachment, attachmentInfo.getUri()), attachmentInfo)); + return attachment; + } catch (CloneNotSupportedException e) { + throw new IllegalArgumentException("Attachment could not be modified", e); } - if (!attachment.getUpdatedBy().equals(user)) { - throw new IllegalArgumentException("User " + user + " did not create the attachment, cannot modify it"); - } - return setAttachmentName(fillTaskMetaEntity(attachment, attachmentInfo.getUri()), attachmentInfo); + } public static Map updateContent(KogitoWorkItem item, MapOutput model) { @@ -96,27 +117,29 @@ public static Map updateContent(KogitoWorkItem item, MapOutput m } public static Map updateContent(KogitoWorkItem item, Map map) { - HumanTaskWorkItemImpl humanTask = asHumanTask(item); + InternalHumanTaskWorkItem humanTask = asHumanTask(item); humanTask.setResults(map); return humanTask.getResults(); } public static boolean deleteComment(KogitoWorkItem item, Object id, String user) { - Map comments = asHumanTask(item).getComments(); + InternalHumanTaskWorkItem humanTask = asHumanTask(item); + Map comments = humanTask.getComments(); Comment comment = comments.get(id); if (comment == null || !comment.getUpdatedBy().equals(user)) { return false; } - return comments.remove(id) != null; + return humanTask.removeComment((String) id) != null; } public static boolean deleteAttachment(KogitoWorkItem item, Object id, String user) { - Map attachments = asHumanTask(item).getAttachments(); + InternalHumanTaskWorkItem humanTask = asHumanTask(item); + Map attachments = humanTask.getAttachments(); Attachment attachment = attachments.get(id); if (attachment == null || !attachment.getUpdatedBy().equals(user)) { return false; } - return attachments.remove(id) != null; + return humanTask.removeAttachment((String) id) != null; } public static HumanTaskWorkItem findTask(ProcessInstance pi, String taskId, Policy... policies) { diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemDecoratorImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemDecoratorImpl.java new file mode 100644 index 00000000000..f5a721cbbd0 --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemDecoratorImpl.java @@ -0,0 +1,456 @@ +/* + * 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.jbpm.process.instance.impl.humantask; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.drools.core.common.InternalKnowledgeRuntime; +import org.jbpm.process.instance.InternalProcessRuntime; +import org.jbpm.workflow.instance.NodeInstance; +import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl; +import org.kie.kogito.internal.process.event.KogitoProcessEventSupport; +import org.kie.kogito.internal.process.event.KogitoProcessEventSupport.AssignmentType; +import org.kie.kogito.internal.process.runtime.KogitoNodeInstance; +import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; +import org.kie.kogito.process.workitem.Attachment; +import org.kie.kogito.process.workitem.Comment; +import org.kie.kogito.process.workitem.Policy; + +public class HumanTaskWorkItemDecoratorImpl implements InternalHumanTaskWorkItem { + + private NodeInstance nodeInstance; + private InternalHumanTaskWorkItem delegate; + + public HumanTaskWorkItemDecoratorImpl(NodeInstance nodeInstance, InternalHumanTaskWorkItem delegate) { + this.nodeInstance = nodeInstance; + this.delegate = delegate; + } + + private InternalKnowledgeRuntime getKieRuntime() { + return ((WorkflowProcessInstanceImpl) nodeInstance.getProcessInstance()).getKnowledgeRuntime(); + } + + private Optional getEventSupport() { + if (!isActive()) { + return Optional.empty(); + } + + if (getKieRuntime() == null) { + return Optional.empty(); + } + + if (getKieRuntime().getProcessRuntime() == null) { + return Optional.empty(); + } + + return Optional.of(InternalProcessRuntime.asKogitoProcessRuntime(getKieRuntime().getProcessRuntime()).getProcessEventSupport()); + } + + private boolean isActive() { + return nodeInstance.getProcessInstance() != null && getKieRuntime() != null; + } + + @Override + public String getTaskName() { + return delegate.getTaskName(); + } + + @Override + public String getTaskDescription() { + return delegate.getTaskDescription(); + } + + @Override + public String getTaskPriority() { + return delegate.getTaskPriority(); + } + + @Override + public String getReferenceName() { + return delegate.getReferenceName(); + } + + @Override + public String getActualOwner() { + return delegate.getActualOwner(); + } + + @Override + public Set getPotentialUsers() { + return delegate.getPotentialUsers(); + } + + @Override + public Set getPotentialGroups() { + return delegate.getPotentialGroups(); + } + + @Override + public Set getAdminUsers() { + return delegate.getAdminUsers(); + } + + @Override + public Set getAdminGroups() { + return delegate.getAdminGroups(); + } + + @Override + public Set getExcludedUsers() { + return delegate.getExcludedUsers(); + } + + @Override + public void setId(String uuid) { + delegate.setId(uuid); + } + + @Override + public void setAttachment(String id, Attachment attachment) { + Attachment oldValue = delegate.getAttachments().get(id); + delegate.setAttachment(id, attachment); + if (oldValue != null) { + getEventSupport().ifPresent(e -> e.fireOnUserTaskAttachmentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), oldValue, attachment)); + } else { + getEventSupport().ifPresent(e -> e.fireOnUserTaskAttachmentAdded(getProcessInstance(), getNodeInstance(), getKieRuntime(), attachment)); + } + } + + @Override + public Attachment removeAttachment(String id) { + Attachment oldValue = delegate.getAttachments().remove(id); + getEventSupport().ifPresent(e -> e.fireOnUserTaskAttachmentDeleted(getProcessInstance(), getNodeInstance(), getKieRuntime(), oldValue)); + return oldValue; + } + + @Override + public void setComment(String id, Comment comment) { + Comment oldValue = delegate.getComments().remove(id); + delegate.setComment(id, comment); + if (oldValue != null) { + getEventSupport().ifPresent(e -> e.fireOnUserTaskCommentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), oldValue, comment)); + } else { + getEventSupport().ifPresent(e -> e.fireOnUserTaskCommentAdded(getProcessInstance(), getNodeInstance(), getKieRuntime(), comment)); + } + + } + + @Override + public Comment removeComment(String id) { + Comment oldValue = delegate.getComments().remove(id); + getEventSupport().ifPresent(e -> e.fireOnUserTaskCommentDeleted(getProcessInstance(), getNodeInstance(), getKieRuntime(), oldValue)); + return oldValue; + } + + @Override + public Map getAttachments() { + return delegate.getAttachments(); + } + + @Override + public Map getComments() { + return delegate.getComments(); + } + + @Override + public long getId() { + return delegate.getId(); + } + + @Override + public String getStringId() { + return delegate.getStringId(); + } + + @Override + public String getProcessInstanceStringId() { + return delegate.getProcessInstanceId(); + } + + @Override + public String getPhaseId() { + return delegate.getPhaseId(); + } + + @Override + public String getPhaseStatus() { + return delegate.getPhaseStatus(); + } + + @Override + public Date getStartDate() { + return delegate.getStartDate(); + } + + @Override + public Date getCompleteDate() { + return delegate.getCompleteDate(); + } + + @Override + public KogitoNodeInstance getNodeInstance() { + return delegate.getNodeInstance(); + } + + @Override + public KogitoProcessInstance getProcessInstance() { + return delegate.getProcessInstance(); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public int getState() { + return delegate.getState(); + } + + @Override + public Object getParameter(String name) { + return delegate.getParameter(name); + } + + @Override + public Map getParameters() { + return delegate.getParameters(); + } + + @Override + public Object getResult(String name) { + return delegate.getResult(name); + } + + @Override + public Map getResults() { + return delegate.getResults(); + } + + @Override + public String getProcessInstanceId() { + return delegate.getProcessInstanceId(); + } + + @Override + public String getNodeInstanceStringId() { + return delegate.getNodeInstanceStringId(); + } + + @Override + public String getDeploymentId() { + return delegate.getDeploymentId(); + } + + @Override + public long getNodeInstanceId() { + return delegate.getNodeInstanceId(); + } + + @Override + public long getNodeId() { + return delegate.getNodeId(); + } + + // set data + @Override + public void setPhaseId(String phaseId) { + delegate.setPhaseId(phaseId); + } + + @Override + public void setProcessInstanceId(String processInstanceId) { + delegate.setProcessInstanceId(processInstanceId); + } + + @Override + public void setNodeInstanceId(String deploymentId) { + delegate.setNodeInstanceId(deploymentId); + } + + @Override + public void setPhaseStatus(String phaseStatus) { + String oldPhaseStatus = delegate.getPhaseStatus(); + delegate.setPhaseStatus(phaseStatus); + getEventSupport().ifPresent(e -> e.fireOneUserTaskStateChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), oldPhaseStatus, phaseStatus)); + + } + + @Override + public void setStartDate(Date date) { + delegate.setStartDate(date); + } + + @Override + public void setCompleteDate(Date date) { + delegate.setCompleteDate(date); + } + + @Override + public void setNodeInstance(KogitoNodeInstance nodeInstance) { + delegate.setNodeInstance(nodeInstance); + } + + @Override + public void setProcessInstance(KogitoProcessInstance processInstance) { + delegate.setProcessInstance(processInstance); + } + + @Override + public void setName(String name) { + delegate.setName(name); + } + + @Override + public void setParameter(String name, Object value) { + Object oldValue = delegate.getParameter(name); + delegate.setParameter(name, value); + getEventSupport().ifPresent(e -> e.fireOnUserTaskInputVariableChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), name, value, oldValue)); + } + + @Override + public void setParameters(Map parameters) { + parameters.forEach(this::setParameter); + } + + @Override + public void setResults(Map results) { + if (results != null) { + results.forEach(this::setResult); + } else { + Map outcome = new HashMap<>(delegate.getResults()); + delegate.setResults(null); + if (isActive()) { + for (String key : outcome.keySet()) { + getEventSupport().ifPresent(e -> e.fireOnUserTaskOutputVariableChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), key, null, outcome.get(key))); + } + } + } + } + + @Override + public void setResult(String name, Object value) { + Object oldValue = delegate.getParameter(name); + delegate.setResult(name, value); + if (isActive()) { + getEventSupport().ifPresent(e -> e.fireOnUserTaskOutputVariableChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), name, value, oldValue)); + } + } + + @Override + public void setState(int state) { + delegate.setState(state); + } + + @Override + public void setDeploymentId(String deploymentId) { + delegate.setDeploymentId(deploymentId); + } + + @Override + public void setNodeInstanceId(long deploymentId) { + delegate.setNodeInstanceId(deploymentId); + } + + @Override + public void setNodeId(long deploymentId) { + delegate.setNodeId(deploymentId); + } + + @Override + public void setTaskName(String taskName) { + delegate.setTaskName(taskName); + + } + + @Override + public void setTaskDescription(String taskDescription) { + delegate.setTaskDescription(taskDescription); + getEventSupport().ifPresent(e -> e.fireOneUserTaskStateChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), delegate.getPhaseStatus(), delegate.getPhaseStatus())); + } + + @Override + public void setTaskPriority(String taskPriority) { + delegate.setTaskPriority(taskPriority); + getEventSupport().ifPresent(e -> e.fireOneUserTaskStateChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), delegate.getPhaseStatus(), delegate.getPhaseStatus())); + } + + @Override + public void setReferenceName(String referenceName) { + delegate.setReferenceName(referenceName); + } + + @Override + public void setActualOwner(String actualOwner) { + String currentPhaseStatus = delegate.getPhaseStatus(); + delegate.setActualOwner(actualOwner); + getEventSupport().ifPresent(e -> e.fireOneUserTaskStateChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), currentPhaseStatus, currentPhaseStatus)); + } + + @Override + public void setPotentialUsers(Set potentialUsers) { + Set oldValue = new HashSet<>(delegate.getPotentialUsers()); + delegate.setPotentialUsers(potentialUsers); + getEventSupport().ifPresent(e -> e.fireOnUserTaskAssignmentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), AssignmentType.USER_OWNERS, oldValue, potentialUsers)); + } + + @Override + public void setPotentialGroups(Set potentialGroups) { + Set oldValue = new HashSet<>(delegate.getPotentialGroups()); + delegate.setPotentialGroups(potentialGroups); + getEventSupport().ifPresent(e -> e.fireOnUserTaskAssignmentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), AssignmentType.USER_GROUPS, oldValue, potentialGroups)); + } + + @Override + public void setAdminGroups(Set potentialAdmins) { + Set oldValue = new HashSet<>(delegate.getAdminGroups()); + delegate.setAdminGroups(potentialAdmins); + getEventSupport().ifPresent(e -> e.fireOnUserTaskAssignmentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), AssignmentType.ADMIN_GROUPS, oldValue, potentialAdmins)); + } + + @Override + public void setAdminUsers(Set adminUsers) { + Set oldValue = new HashSet<>(delegate.getAdminUsers()); + delegate.setAdminUsers(adminUsers); + getEventSupport().ifPresent(e -> e.fireOnUserTaskAssignmentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), AssignmentType.ADMIN_USERS, oldValue, adminUsers)); + + } + + @Override + public void setExcludedUsers(Set excludedUsers) { + Set oldValue = new HashSet<>(delegate.getExcludedUsers()); + delegate.setExcludedUsers(excludedUsers); + getEventSupport().ifPresent(e -> e.fireOnUserTaskAssignmentChange(getProcessInstance(), getNodeInstance(), getKieRuntime(), AssignmentType.USERS_EXCLUDED, oldValue, excludedUsers)); + } + + @Override + public boolean enforce(Policy... policies) { + return delegate.enforce(policies); + } + + @Override + public String toString() { + return delegate.toString(); + } +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemImpl.java index 892b9ed68c4..a1c1a77c39b 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/HumanTaskWorkItemImpl.java @@ -28,14 +28,13 @@ import org.kie.kogito.auth.SecurityPolicy; import org.kie.kogito.process.workitem.Attachment; import org.kie.kogito.process.workitem.Comment; -import org.kie.kogito.process.workitem.HumanTaskWorkItem; import org.kie.kogito.process.workitem.NotAuthorizedException; import org.kie.kogito.process.workitem.Policy; import org.kie.kogito.process.workitems.impl.KogitoWorkItemImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class HumanTaskWorkItemImpl extends KogitoWorkItemImpl implements HumanTaskWorkItem { +public class HumanTaskWorkItemImpl extends KogitoWorkItemImpl implements InternalHumanTaskWorkItem { private static final long serialVersionUID = 6168927742199190604L; private static final Logger logger = LoggerFactory.getLogger(HumanTaskWorkItemImpl.class); @@ -212,4 +211,24 @@ public Map getAttachments() { public Map getComments() { return comments; } + + @Override + public void setAttachment(String id, Attachment attachment) { + attachments.put(id, attachment); + } + + @Override + public Attachment removeAttachment(String id) { + return attachments.remove(id); + } + + @Override + public void setComment(String id, Comment comment) { + comments.put(id, comment); + } + + @Override + public Comment removeComment(String id) { + return comments.remove(1); + } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/InternalHumanTaskWorkItem.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/InternalHumanTaskWorkItem.java new file mode 100644 index 00000000000..75180fd91a9 --- /dev/null +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/InternalHumanTaskWorkItem.java @@ -0,0 +1,59 @@ +/* + * 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.jbpm.process.instance.impl.humantask; + +import java.util.Set; + +import org.kie.kogito.process.workitem.Attachment; +import org.kie.kogito.process.workitem.Comment; +import org.kie.kogito.process.workitem.HumanTaskWorkItem; +import org.kie.kogito.process.workitems.InternalKogitoWorkItem; + +public interface InternalHumanTaskWorkItem extends HumanTaskWorkItem, InternalKogitoWorkItem { + + void setTaskName(String parameter); + + void setTaskDescription(String parameter); + + void setTaskPriority(String parameter); + + void setReferenceName(String parameter); + + void setActualOwner(String string); + + void setPotentialUsers(Set potentialUsers); + + void setPotentialGroups(Set potentialGroups); + + void setAdminGroups(Set potentialGroups); + + void setAdminUsers(Set adminUsers); + + void setExcludedUsers(Set excludedUsers); + + void setAttachment(String id, Attachment attachment); + + void setComment(String id, Comment comment); + + Comment removeComment(String id); + + Attachment removeAttachment(String id); + +} diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Claim.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Claim.java index 427d33d2e5a..19a090ccdc4 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Claim.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Claim.java @@ -21,7 +21,7 @@ import java.util.Arrays; import java.util.List; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.workitem.Active; import org.kie.kogito.auth.SecurityPolicy; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; @@ -72,12 +72,12 @@ public void apply(KogitoWorkItem workitem, Transition transition) { if (transition.policies() != null) { for (Policy policy : transition.policies()) { if (policy instanceof SecurityPolicy) { - ((HumanTaskWorkItemImpl) workitem).setActualOwner(((SecurityPolicy) policy).value().getName()); + ((InternalHumanTaskWorkItem) workitem).setActualOwner(((SecurityPolicy) policy).value().getName()); break; } } } - workitem.getResults().put("ActorId", ((HumanTaskWorkItem) workitem).getActualOwner()); + ((InternalHumanTaskWorkItem) workitem).setResult("ActorId", ((HumanTaskWorkItem) workitem).getActualOwner()); } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Release.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Release.java index 17e8b593aa2..7919f00d41a 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Release.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Release.java @@ -21,7 +21,7 @@ import java.util.Arrays; import java.util.List; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; import org.kie.kogito.process.workitem.LifeCyclePhase; import org.kie.kogito.process.workitem.Transition; @@ -64,7 +64,6 @@ public boolean canTransition(LifeCyclePhase phase) { @Override public void apply(KogitoWorkItem workitem, Transition transition) { - - ((HumanTaskWorkItemImpl) workitem).setActualOwner(null); + ((InternalHumanTaskWorkItem) workitem).setActualOwner(null); } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Skip.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Skip.java index f53ba0b13e8..db5bd4d8285 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Skip.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/humantask/phases/Skip.java @@ -21,7 +21,7 @@ import java.util.Arrays; import java.util.List; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.workitem.Active; import org.kie.kogito.auth.SecurityPolicy; import org.kie.kogito.internal.process.runtime.KogitoWorkItem; @@ -75,11 +75,11 @@ public void apply(KogitoWorkItem workitem, Transition transition) { if (transition.policies() != null) { for (Policy policy : transition.policies()) { if (policy instanceof SecurityPolicy) { - ((HumanTaskWorkItemImpl) workitem).setActualOwner(((SecurityPolicy) policy).value().getName()); + ((InternalHumanTaskWorkItem) workitem).setActualOwner(((SecurityPolicy) policy).value().getName()); break; } } } - workitem.getResults().put("ActorId", ((HumanTaskWorkItem) workitem).getActualOwner()); + ((InternalHumanTaskWorkItem) workitem).setResult("ActorId", ((HumanTaskWorkItem) workitem).getActualOwner()); } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/workitem/Complete.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/workitem/Complete.java index 8acb5246034..23478e6346b 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/workitem/Complete.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/impl/workitem/Complete.java @@ -21,7 +21,7 @@ import java.util.Arrays; import java.util.List; -import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.humantask.phases.Claim; import org.jbpm.process.instance.impl.humantask.phases.Release; import org.kie.kogito.auth.SecurityPolicy; @@ -77,12 +77,12 @@ public void apply(KogitoWorkItem workitem, Transition transition) { if (transition.policies() != null) { for (Policy policy : transition.policies()) { if (policy instanceof SecurityPolicy) { - ((HumanTaskWorkItemImpl) workitem).setActualOwner(((SecurityPolicy) policy).value().getName()); + ((InternalHumanTaskWorkItem) workitem).setActualOwner(((SecurityPolicy) policy).value().getName()); break; } } } - workitem.getResults().put("ActorId", ((HumanTaskWorkItem) workitem).getActualOwner()); + ((InternalHumanTaskWorkItem) workitem).setResult("ActorId", ((HumanTaskWorkItem) workitem).getActualOwner()); } } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java index 47c3ea59089..c9e82a7dfe9 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java @@ -105,6 +105,11 @@ protected void setId(Object node, Object id) { getRuleFlowProcess().setId((String) id); } + public RuleFlowProcessFactory expressionLanguage(String exprLanguage) { + getRuleFlowProcess().setExpressionLanguage(exprLanguage); + return this; + } + protected RuleFlowProcess getRuleFlowProcess() { return (RuleFlowProcess) node; } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/ForEachNodeFactory.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/ForEachNodeFactory.java index 3ec066530ed..aa462310aec 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/ForEachNodeFactory.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/ForEachNodeFactory.java @@ -73,11 +73,6 @@ public ForEachNodeFactory outputCollectionExpression(String collectionExpress return this; } - public ForEachNodeFactory expressionLanguage(String exprLanguage) { - getForEachNode().setExpressionLanguage(exprLanguage); - return this; - } - public ForEachNodeFactory completionAction(Action completionAction) { getForEachNode().setCompletionAction(completionAction); return this; diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/validation/RuleFlowProcessValidator.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/validation/RuleFlowProcessValidator.java index fa7c93b3c8d..831354914db 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/validation/RuleFlowProcessValidator.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/validation/RuleFlowProcessValidator.java @@ -81,6 +81,7 @@ import org.kie.api.definition.process.Process; import org.kie.api.io.Resource; import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess; +import org.kie.kogito.process.expr.ExpressionHandlerFactory; import static java.lang.String.format; import static org.jbpm.ruleflow.core.Metadata.EVENT_TYPE; @@ -855,6 +856,11 @@ private boolean acceptsNoOutgoingConnections(org.kie.api.definition.process.Node (nodeContainer instanceof WorkflowProcess && ((WorkflowProcess) nodeContainer).isDynamic()); } + private boolean isExpression(RuleFlowProcess process, String expression) { + String lang = process.getExpressionLanguage(); + return lang != null && ExpressionHandlerFactory.get(lang, expression).isValid(); + } + private void validateTimer(final Timer timer, final org.kie.api.definition.process.Node node, final RuleFlowProcess process, @@ -884,10 +890,12 @@ private void validateTimer(final Timer timer, break; } } catch (RuntimeException e) { - addErrorMessage(process, - node, - errors, - "Could not parse delay '" + timer.getDelay() + "': " + e.getMessage()); + if (!isExpression(process, timer.getDelay())) { + addErrorMessage(process, + node, + errors, + "Could not parse delay '" + timer.getDelay() + "': " + e.getMessage()); + } } } } @@ -898,10 +906,12 @@ private void validateTimer(final Timer timer, DateTimeUtils.parseRepeatableDateTime(timer.getPeriod()); } } catch (RuntimeException e) { - addErrorMessage(process, - node, - errors, - "Could not parse period '" + timer.getPeriod() + "': " + e.getMessage()); + if (!isExpression(process, timer.getPeriod())) { + addErrorMessage(process, + node, + errors, + "Could not parse period '" + timer.getPeriod() + "': " + e.getMessage()); + } } } @@ -909,10 +919,12 @@ private void validateTimer(final Timer timer, try { DateTimeUtils.parseDateAsDuration(timer.getDate()); } catch (RuntimeException e) { - addErrorMessage(process, - node, - errors, - "Could not parse date '" + timer.getDate() + "': " + e.getMessage()); + if (!isExpression(process, timer.getDate())) { + addErrorMessage(process, + node, + errors, + "Could not parse date '" + timer.getDate() + "': " + e.getMessage()); + } } } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/WorkflowProcess.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/WorkflowProcess.java index fd04d3ebd51..b25e001e915 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/WorkflowProcess.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/WorkflowProcess.java @@ -58,4 +58,7 @@ public interface WorkflowProcess extends KogitoWorkflowProcess, Process, NodeCon void setOutputValidator(WorkflowModelValidator validator); + void setExpressionLanguage(String exprLanguage); + + String getExpressionLanguage(); } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java index e364abaafc2..e58e08bb249 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java @@ -28,8 +28,10 @@ import org.jbpm.process.core.Context; import org.jbpm.process.core.ContextResolver; import org.jbpm.process.core.context.variable.Mappable; +import org.jbpm.ruleflow.core.RuleFlowProcess; import org.jbpm.workflow.core.Constraint; import org.jbpm.workflow.core.Node; +import org.jbpm.workflow.core.WorkflowProcess; import org.jbpm.workflow.core.node.CompositeNode; import org.kie.api.definition.process.Connection; import org.kie.api.definition.process.NodeContainer; @@ -80,52 +82,72 @@ public IOSpecification getIoSpecification() { return ioSpecification; } + @Override public Map getInMappings() { return getIoSpecification().getInputMapping(); } + @Override public Map getOutMappings() { return getIoSpecification().getOutputMappingBySources(); } + @Override public String getInMapping(String key) { return getIoSpecification().getInputMapping().get(key); } + @Override public String getOutMapping(String key) { return getIoSpecification().getOutputMappingBySources().get(key); } + @Override public void addInMapping(String from, String to) { getIoSpecification().addInputMapping(from, to); } + @Override public void addOutMapping(String from, String to) { getIoSpecification().addOutputMapping(from, to); } + @Override public void addInAssociation(DataAssociation dataAssociation) { getIoSpecification().getDataInputs().add(dataAssociation.getTarget()); getIoSpecification().getDataInputAssociation().add(dataAssociation); } + @Override public List getInAssociations() { return getIoSpecification().getDataInputAssociation(); } + @Override public void addOutAssociation(DataAssociation dataAssociation) { dataAssociation.getSources().forEach(s -> getIoSpecification().getDataOutputs().add(s)); getIoSpecification().getDataOutputAssociation().add(dataAssociation); } + public WorkflowProcess getProcess() { + NodeContainer container = parentContainer; + while (!(container instanceof RuleFlowProcess)) { + container = ((NodeImpl) container).parentContainer; + } + return (WorkflowProcess) container; + } + + @Override public List getOutAssociations() { return getIoSpecification().getDataOutputAssociation(); } + @Override public long getId() { return this.id; } + @Override public String getUniqueId() { StringBuilder result = new StringBuilder(id + ""); NodeContainer nodeContainer = getParentContainer(); @@ -137,6 +159,7 @@ public String getUniqueId() { return result.toString(); } + @Override public void setId(final long id) { this.id = id; String uniqueId = (String) getMetaData("UniqueId"); @@ -145,24 +168,29 @@ public void setId(final long id) { } } + @Override public String getName() { return this.name; } + @Override public void setName(final String name) { this.name = name; } + @Override public Map> getIncomingConnections() { // TODO: users can still modify the lists inside this Map return Collections.unmodifiableMap(this.incomingConnections); } + @Override public Map> getOutgoingConnections() { // TODO: users can still modify the lists inside this Map return Collections.unmodifiableMap(this.outgoingConnections); } + @Override public void addIncomingConnection(final String type, final Connection connection) { validateAddIncomingConnection(type, connection); List connections = this.incomingConnections.get(type); @@ -182,6 +210,7 @@ public void validateAddIncomingConnection(final String type, final Connection co } } + @Override public List getIncomingConnections(String type) { List result = incomingConnections.get(type); if (result == null) { @@ -190,6 +219,7 @@ public List getIncomingConnections(String type) { return result; } + @Override public void addOutgoingConnection(final String type, final Connection connection) { validateAddOutgoingConnection(type, connection); List connections = this.outgoingConnections.get(type); @@ -209,6 +239,7 @@ public void validateAddOutgoingConnection(final String type, final Connection co } } + @Override public List getOutgoingConnections(String type) { List result = outgoingConnections.get(type); if (result == null) { @@ -217,6 +248,7 @@ public List getOutgoingConnections(String type) { return result; } + @Override public void removeIncomingConnection(final String type, final Connection connection) { validateRemoveIncomingConnection(type, connection); this.incomingConnections.get(type).remove(connection); @@ -243,6 +275,7 @@ public void validateRemoveIncomingConnection(final String type, final Connection } } + @Override public void removeOutgoingConnection(final String type, final Connection connection) { validateRemoveOutgoingConnection(type, connection); this.outgoingConnections.get(type).remove(connection); @@ -315,22 +348,27 @@ public List getDefaultOutgoingConnections() { return getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE); } + @Override public NodeContainer getParentContainer() { return parentContainer; } + @Override public void setParentContainer(NodeContainer nodeContainer) { this.parentContainer = nodeContainer; } + @Override public void setContext(String contextId, Context context) { this.contexts.put(contextId, context); } + @Override public Context getContext(String contextId) { return this.contexts.get(contextId); } + @Override public Context resolveContext(String contextId, Object param) { Context context = getContext(contextId); if (context != null) { @@ -342,6 +380,7 @@ public Context resolveContext(String contextId, Object param) { return ((org.jbpm.workflow.core.NodeContainer) parentContainer).resolveContext(contextId, param); } + @Override public void setMetaData(String name, Object value) { this.metaData.put(name, value); } @@ -350,6 +389,7 @@ public Object getMetaData(String name) { return this.metaData.get(name); } + @Override public Map getMetaData() { return this.metaData; } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/WorkflowProcessImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/WorkflowProcessImpl.java index b8ed36b4e8d..667a34e1ff8 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/WorkflowProcessImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/WorkflowProcessImpl.java @@ -55,6 +55,7 @@ public class WorkflowProcessImpl extends ProcessImpl implements WorkflowProcess, private WorkflowModelValidator inputValidator; private WorkflowModelValidator outputValidator; private org.jbpm.workflow.core.NodeContainer nodeContainer; + private String exprLanguage; private transient BiFunction expressionEvaluator = (expression, p) -> { @@ -239,4 +240,12 @@ public Optional getOutputValidator() { public void setOutputValidator(WorkflowModelValidator outputValidator) { this.outputValidator = outputValidator; } + + public void setExpressionLanguage(String exprLanguage) { + this.exprLanguage = exprLanguage; + } + + public String getExpressionLanguage() { + return exprLanguage; + } } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java index 78012071081..f96f9476ad3 100644 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java @@ -149,9 +149,9 @@ protected KogitoEventListener getEventListener() { } @Override - public void cancel() { + public void cancel(CancelType cancelType) { ((InternalProcessRuntime) getProcessInstance().getKnowledgeRuntime().getProcessRuntime()).getJobsService().cancelJob(getJobId()); - super.cancel(); + super.cancel(cancelType); } public String getJobId() { diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ForEachNode.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ForEachNode.java index a13fd0557b0..8b7ea883ad4 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ForEachNode.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ForEachNode.java @@ -50,7 +50,7 @@ public class ForEachNode extends CompositeContextNode { private String collectionExpression; private String outputCollectionExpression; private String completionConditionExpression; - private String exprLanguage; + private Action finishAction; private boolean waitForCompletion = true; private Expression evaluateExpression; @@ -108,14 +108,6 @@ public DataType getVariableType() { return null; } - public void setExpressionLanguage(String exprLanguage) { - this.exprLanguage = exprLanguage; - } - - public String getExpressionLanguage() { - return exprLanguage; - } - public Action getCompletionAction() { return finishAction; } @@ -125,6 +117,7 @@ public void setCompletionAction(Action finishAction) { } public Expression getEvaluateExpression() { + String exprLanguage = getProcess().getExpressionLanguage(); if (evaluateExpression == null && ExpressionHandlerFactory.isSupported(exprLanguage)) { evaluateExpression = ExpressionHandlerFactory.get(exprLanguage, collectionExpression); } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/NodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/NodeInstance.java index 1313ba42f42..98a32475c0c 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/NodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/NodeInstance.java @@ -39,6 +39,8 @@ public interface NodeInstance extends KogitoNodeInstance { void cancel(); + void cancel(CancelType type); + Node getNode(); ContextInstance resolveContextInstance(String contextId, Object param); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java index 280bccf9dc4..af9134308dc 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java @@ -90,6 +90,8 @@ public abstract class NodeInstanceImpl implements org.jbpm.workflow.instance.Nod protected Date triggerTime; protected Date leaveTime; + protected transient CancelType cancelType; + protected transient Map dynamicParameters; public void setId(final String id) { @@ -173,11 +175,22 @@ public boolean isInversionOfControl() { return false; } + public CancelType getCancelType() { + return cancelType; + } + + public final void cancel() { + cancel(CancelType.ABORTED); + } + @Override - public void cancel() { + public void cancel(CancelType cancelType) { + this.cancelType = cancelType; + if (triggerTime == null) { triggerTime = new Date(); } + leaveTime = new Date(); boolean hidden = false; org.kie.api.definition.process.Node node = getNode(); @@ -264,7 +277,7 @@ protected void executeAction(Action action, KogitoProcessContext context) { } context.getContextData().put("Exception", e); exceptionScopeInstance.handleException(e, context); - cancel(); + cancel(CancelType.ERROR); } } @@ -398,7 +411,7 @@ protected org.jbpm.workflow.instance.NodeInstance followConnection(Connection co if (groupInstance.containsNodeInstance(this)) { for (KogitoNodeInstance nodeInstance : groupInstance.getNodeInstances()) { if (nodeInstance != this) { - ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel(); + ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel(CancelType.OBSOLETE); } } ((ContextInstanceContainer) parent).removeContextInstance(ExclusiveGroup.EXCLUSIVE_GROUP, contextInstance); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java index 67922d5a8a4..f095f8f1b2b 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java @@ -1142,6 +1142,7 @@ public void setErrorState(NodeInstance nodeInstanceInError, Exception e) { this.errorMessage = rootException.getClass().getCanonicalName() + " - " + rootException.getMessage(); setState(STATE_ERROR); logger.error("Unexpected error while executing node {} in process instance {}", nodeInstanceInError.getNode().getName(), this.getStringId(), e); + e.printStackTrace(); // remove node instance that caused an error ((org.jbpm.workflow.instance.NodeInstanceContainer) nodeInstanceInError.getNodeInstanceContainer()).removeNodeInstance(nodeInstanceInError); } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/BoundaryEventNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/BoundaryEventNodeInstance.java index cb71f42ec0b..fa533366093 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/BoundaryEventNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/BoundaryEventNodeInstance.java @@ -88,7 +88,7 @@ private boolean isAttachedToNodeCompleted(String attachedTo) { } @Override - public void cancel() { + public void cancel(CancelType cancelType) { getProcessInstance().removeEventListener(getEventType(), getEventListener(), true); ((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this); } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java index 938c65c2d5c..f07a0bccc0f 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/CompositeNodeInstance.java @@ -172,18 +172,18 @@ public void triggerCompleted(String outType) { if (cancelRemainingInstances) { while (!nodeInstances.isEmpty()) { NodeInstance nodeInstance = nodeInstances.get(0); - nodeInstance.cancel(); + nodeInstance.cancel(CancelType.OBSOLETE); } } } @Override - public void cancel() { + public void cancel(CancelType cancelType) { while (!nodeInstances.isEmpty()) { NodeInstance nodeInstance = nodeInstances.get(0); - nodeInstance.cancel(); + nodeInstance.cancel(cancelType); } - super.cancel(); + super.cancel(cancelType); } @Override diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/DynamicUtils.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/DynamicUtils.java index 403d73f6559..f7b0f23ab24 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/DynamicUtils.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/DynamicUtils.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.regex.Matcher; import org.drools.core.common.InternalWorkingMemory; @@ -93,6 +94,7 @@ private static void internalAddDynamicWorkItem( String workItemName, Map parameters) { final KogitoWorkItemImpl workItem = new KogitoWorkItemImpl(); + workItem.setId(UUID.randomUUID().toString()); workItem.setState(WorkItem.ACTIVE); workItem.setProcessInstanceId(processInstance.getStringId()); workItem.setDeploymentId((String) ksession.getEnvironment().get(EnvironmentName.DEPLOYMENT_ID)); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EndNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EndNodeInstance.java index 939150675cc..37aa10757a0 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EndNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EndNodeInstance.java @@ -67,7 +67,7 @@ public void internalTrigger(KogitoNodeInstance from, String type) { getProcessInstance().setState(KogitoProcessInstance.STATE_COMPLETED); } else { while (!getNodeInstanceContainer().getNodeInstances().isEmpty()) { - ((org.jbpm.workflow.instance.NodeInstance) getNodeInstanceContainer().getNodeInstances().iterator().next()).cancel(); + ((org.jbpm.workflow.instance.NodeInstance) getNodeInstanceContainer().getNodeInstances().iterator().next()).cancel(CancelType.OBSOLETE); } ((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null); } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java index d88afa71fac..bf4edf3b688 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java @@ -156,7 +156,7 @@ public void triggerCompleted() { } @Override - public void cancel() { + public void cancel(CancelType cancelType) { getProcessInstance().removeEventListener(getEventType(), getEventListener(), true); removeTimerListeners(); if (this.slaCompliance == KogitoProcessInstance.SLA_PENDING) { @@ -168,7 +168,7 @@ public void cancel() { } } removeTimerListeners(); - super.cancel(); + super.cancel(cancelType); } private class VariableExternalEventListener implements KogitoEventListener, Serializable { diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/HumanTaskNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/HumanTaskNodeInstance.java index 7ef2179a393..e9738f7f4af 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/HumanTaskNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/HumanTaskNodeInstance.java @@ -19,6 +19,7 @@ package org.jbpm.workflow.instance.node; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -34,6 +35,7 @@ import org.jbpm.process.instance.impl.humantask.DeadlineInfo; import org.jbpm.process.instance.impl.humantask.HumanTaskHelper; import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.humantask.Reassignment; import org.jbpm.process.instance.impl.humantask.ScheduleInfo; import org.jbpm.workflow.core.node.HumanTaskNode; @@ -74,9 +76,19 @@ public HumanTaskNode getHumanTaskNode() { return (HumanTaskNode) getNode(); } + @Override + public InternalHumanTaskWorkItem getWorkItem() { + return (InternalHumanTaskWorkItem) super.getWorkItem(); + } + + protected InternalKogitoWorkItem decorate(InternalKogitoWorkItem kogitoWorkItem) { + this.getKogitoProcessInstance(); + return HumanTaskHelper.decorate(this, (InternalHumanTaskWorkItem) kogitoWorkItem); + } + @Override protected InternalKogitoWorkItem newWorkItem() { - return new HumanTaskWorkItemImpl(); + return HumanTaskHelper.decorate(this, new HumanTaskWorkItemImpl()); } /* @@ -107,7 +119,7 @@ public Map getNotCompletedReassigments() { @Override protected InternalKogitoWorkItem createWorkItem(WorkItemNode workItemNode) { - HumanTaskWorkItemImpl workItem = (HumanTaskWorkItemImpl) super.createWorkItem(workItemNode); + InternalHumanTaskWorkItem workItem = (InternalHumanTaskWorkItem) super.createWorkItem(workItemNode); String actorId = assignWorkItem(workItem); if (actorId != null) { workItem.setParameter(ACTOR_ID, actorId); @@ -225,18 +237,18 @@ private JobsService getJobsService() { } private void startNotification(Map notification) { - getEventSupport().fireOnTaskNotStartedDeadline(getProcessInstance(), (HumanTaskWorkItem) getWorkItem(), + getEventSupport().fireOnUserTaskNotStartedDeadline(getProcessInstance(), this, (HumanTaskWorkItem) getWorkItem(), notification, getProcessInstance().getKnowledgeRuntime()); } private void endNotification(Map notification) { - getEventSupport().fireOnTaskNotCompletedDeadline(getProcessInstance(), (HumanTaskWorkItem) getWorkItem(), + getEventSupport().fireOnUserTaskNotCompletedDeadline(getProcessInstance(), this, (HumanTaskWorkItem) getWorkItem(), notification, getProcessInstance().getKnowledgeRuntime()); } private void reassign(Reassignment reassignment) { - HumanTaskWorkItemImpl humanTask = HumanTaskHelper.asHumanTask(getWorkItem()); + InternalHumanTaskWorkItem humanTask = HumanTaskHelper.asHumanTask(getWorkItem()); boolean modified = false; if (!reassignment.getPotentialUsers().isEmpty()) { humanTask.setPotentialUsers(reassignment.getPotentialUsers()); @@ -271,11 +283,27 @@ protected String assignWorkItem(InternalKogitoWorkItem workItem) { } } - processAssigment(ACTOR_ID, workItem, ((HumanTaskWorkItemImpl) workItem).getPotentialUsers()); - processAssigment(GROUP_ID, workItem, ((HumanTaskWorkItemImpl) workItem).getPotentialGroups()); - processAssigment(EXCLUDED_OWNER_ID, workItem, ((HumanTaskWorkItemImpl) workItem).getExcludedUsers()); - processAssigment(BUSINESSADMINISTRATOR_ID, workItem, ((HumanTaskWorkItemImpl) workItem).getAdminUsers()); - processAssigment(BUSINESSADMINISTRATOR_GROUP_ID, workItem, ((HumanTaskWorkItemImpl) workItem).getAdminGroups()); + InternalHumanTaskWorkItem hunanWorkItem = (InternalHumanTaskWorkItem) workItem; + + Set newPUValue = new HashSet<>(hunanWorkItem.getPotentialUsers()); + processAssigment(ACTOR_ID, workItem, newPUValue); + hunanWorkItem.setPotentialUsers(newPUValue); + + Set newPGValue = new HashSet<>(hunanWorkItem.getPotentialGroups()); + processAssigment(GROUP_ID, workItem, newPGValue); + hunanWorkItem.setPotentialGroups(newPGValue); + + Set newEUValue = new HashSet<>(hunanWorkItem.getExcludedUsers()); + processAssigment(EXCLUDED_OWNER_ID, workItem, newEUValue); + hunanWorkItem.setExcludedUsers(newEUValue); + + Set newAUValue = new HashSet<>(hunanWorkItem.getAdminUsers()); + processAssigment(BUSINESSADMINISTRATOR_ID, workItem, newAUValue); + hunanWorkItem.setAdminGroups(newAUValue); + + Set newAGValue = new HashSet<>(hunanWorkItem.getAdminGroups()); + processAssigment(BUSINESSADMINISTRATOR_GROUP_ID, workItem, newAGValue); + hunanWorkItem.setAdminGroups(newAGValue); // always return ActorId from workitem as SwimlaneActorId is kept as separate parameter return (String) workItem.getParameter(ACTOR_ID); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/LambdaSubProcessNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/LambdaSubProcessNodeInstance.java index 49bd601a119..23bbc7c5577 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/LambdaSubProcessNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/LambdaSubProcessNodeInstance.java @@ -116,8 +116,8 @@ private boolean hasAsyncNodeInstance(org.kie.api.runtime.process.ProcessInstance } @Override - public void cancel() { - super.cancel(); + public void cancel(CancelType cancelType) { + super.cancel(cancelType); if (getSubProcessNode() == null || !getSubProcessNode().isIndependent()) { ProcessInstance processInstance = null; KogitoProcessRuntime kruntime = (KogitoProcessRuntime) ((ProcessInstance) getProcessInstance()).getKnowledgeRuntime(); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/RuleSetNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/RuleSetNodeInstance.java index 99705255f3f..9640a815222 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/RuleSetNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/RuleSetNodeInstance.java @@ -125,8 +125,8 @@ public void removeEventListeners() { } @Override - public void cancel() { - super.cancel(); + public void cancel(CancelType cancelType) { + super.cancel(cancelType); if (actAsWaitState()) { ((InternalAgenda) getProcessInstance().getKnowledgeRuntime().getAgenda()).getAgendaGroupsManager().deactivateRuleFlowGroup(getRuleFlowGroup()); } diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java index 001e0a9a190..68d8150838b 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java @@ -34,8 +34,11 @@ import org.jbpm.process.core.timer.Timer; import org.jbpm.process.instance.InternalProcessRuntime; import org.jbpm.process.instance.impl.Action; +import org.jbpm.ruleflow.core.Metadata; import org.jbpm.util.ContextFactory; import org.jbpm.workflow.core.DroolsAction; +import org.jbpm.workflow.core.WorkflowProcess; +import org.jbpm.workflow.core.impl.NodeImpl; import org.jbpm.workflow.core.node.StateBasedNode; import org.jbpm.workflow.instance.impl.ExtendedNodeInstanceImpl; import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl; @@ -51,6 +54,8 @@ import org.kie.kogito.jobs.ExpirationTime; import org.kie.kogito.jobs.JobsService; import org.kie.kogito.jobs.ProcessInstanceJobDescription; +import org.kie.kogito.process.expr.Expression; +import org.kie.kogito.process.expr.ExpressionHandlerFactory; import org.kie.kogito.timer.TimerInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,6 +73,8 @@ public abstract class StateBasedNodeInstance extends ExtendedNodeInstanceImpl im private Map timerInstancesReference; + private transient KogitoProcessContext context; + public StateBasedNode getEventBasedNode() { return (StateBasedNode) getNode(); } @@ -144,8 +151,8 @@ protected ExpirationTime createTimerInstance(Timer timer) { switch (timer.getTimeType()) { case Timer.TIME_CYCLE: - String tempDelay = resolveExpression(timer.getDelay()); - String tempPeriod = resolveExpression(timer.getPeriod()); + String tempDelay = resolveTimerExpression(timer.getDelay()); + String tempPeriod = resolveTimerExpression(timer.getPeriod()); if (DateTimeUtils.isRepeatable(tempDelay)) { String[] values = DateTimeUtils.parseISORepeatable(tempDelay); String tempRepeatLimit = values[0]; @@ -174,7 +181,7 @@ protected ExpirationTime createTimerInstance(Timer timer) { } case Timer.TIME_DURATION: - delay = resolveExpression(timer.getDelay()); + delay = resolveTimerExpression(timer.getDelay()); return DurationExpirationTime.repeat(businessCalendar.calculateBusinessTimeAsDuration(delay)); case Timer.TIME_DATE: @@ -196,14 +203,14 @@ protected ExpirationTime configureTimerInstance(Timer timer) { case Timer.TIME_CYCLE: if (timer.getPeriod() != null) { - long actualDelay = DateTimeUtils.parseDuration(resolveExpression(timer.getDelay())); + long actualDelay = DateTimeUtils.parseDuration(resolveTimerExpression(timer.getDelay())); if (timer.getPeriod() == null) { return DurationExpirationTime.repeat(actualDelay, actualDelay, Integer.MAX_VALUE); } else { - return DurationExpirationTime.repeat(actualDelay, DateTimeUtils.parseDuration(resolveExpression(timer.getPeriod())), Integer.MAX_VALUE); + return DurationExpirationTime.repeat(actualDelay, DateTimeUtils.parseDuration(resolveTimerExpression(timer.getPeriod())), Integer.MAX_VALUE); } } else { - String resolvedDelay = resolveExpression(timer.getDelay()); + String resolvedDelay = resolveTimerExpression(timer.getDelay()); // when using ISO date/time period is not set long[] repeatValues = null; @@ -233,7 +240,7 @@ protected ExpirationTime configureTimerInstance(Timer timer) { duration = DateTimeUtils.parseDuration(timer.getDelay()); } catch (RuntimeException e) { // cannot parse delay, trying to interpret it - s = resolveExpression(timer.getDelay()); + s = resolveTimerExpression(timer.getDelay()); duration = DateTimeUtils.parseDuration(s); } return DurationExpirationTime.after(duration); @@ -243,13 +250,32 @@ protected ExpirationTime configureTimerInstance(Timer timer) { return ExactExpirationTime.of(timer.getDate()); } catch (RuntimeException e) { // cannot parse delay, trying to interpret it - s = resolveExpression(timer.getDate()); + s = resolveTimerExpression(timer.getDate()); return ExactExpirationTime.of(s); } } throw new UnsupportedOperationException("Not supported timer definition"); } + private String resolveTimerExpression(String expression) { + if (!isExpression(expression)) { + WorkflowProcess process = ((NodeImpl) getNode()).getProcess(); + String lang = process.getExpressionLanguage(); + if (lang != null) { + Expression exprObject = ExpressionHandlerFactory.get(lang, expression); + if (exprObject.isValid()) { + if (context == null) { + context = ContextFactory.fromNode(this); + } + String varName = (String) process.getMetaData().get(Metadata.VARIABLE); + Object target = varName == null ? this.getProcessInstance().getVariables() : context.getVariable(varName); + return exprObject.eval(target, String.class, context); + } + } + } + return resolveExpression(expression); + } + protected void handleSLAViolation() { if (slaCompliance == KogitoProcessInstance.SLA_PENDING) { InternalProcessRuntime processRuntime = ((InternalProcessRuntime) getProcessInstance().getKnowledgeRuntime().getProcessRuntime()); @@ -361,7 +387,7 @@ public void internalSetTimerInstancesReference(Map timerInstance } @Override - public void cancel() { + public void cancel(CancelType cancelType) { if (this.slaCompliance == KogitoProcessInstance.SLA_PENDING) { if (System.currentTimeMillis() > slaDueDate.getTime()) { // completion of the process instance is after expected SLA due date, mark it accordingly @@ -374,7 +400,7 @@ public void cancel() { cancelTimers(); removeEventListeners(); removeActivationListener(); - super.cancel(); + super.cancel(cancelType); } private void cancelTimers() { diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/SubProcessNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/SubProcessNodeInstance.java index 130b47fec2f..0177b114f65 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/SubProcessNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/SubProcessNodeInstance.java @@ -154,8 +154,8 @@ public void internalTrigger(final KogitoNodeInstance from, String type) { } @Override - public void cancel() { - super.cancel(); + public void cancel(CancelType cancelType) { + super.cancel(cancelType); if (getSubProcessNode() == null || !getSubProcessNode().isIndependent()) { KogitoProcessRuntime kruntime = InternalProcessRuntime.asKogitoProcessRuntime(getProcessInstance().getKnowledgeRuntime()); diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java index 9f54742fd43..c095d861bc7 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java @@ -27,7 +27,9 @@ import java.util.Set; import java.util.UUID; +import org.jbpm.process.core.context.exception.ExceptionScope; import org.jbpm.process.instance.InternalProcessRuntime; +import org.jbpm.process.instance.context.exception.ExceptionScopeInstance; import org.jbpm.workflow.core.Node; import org.jbpm.workflow.core.node.TimerNode; import org.kie.api.runtime.process.EventListener; @@ -37,11 +39,15 @@ import org.kie.kogito.jobs.ProcessInstanceJobDescription; import org.kie.kogito.process.BaseEventDescription; import org.kie.kogito.process.EventDescription; +import org.kie.kogito.process.workitem.WorkItemExecutionException; import org.kie.kogito.services.uow.BaseWorkUnit; import org.kie.kogito.timer.TimerInstance; import org.kie.kogito.uow.WorkUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TimerNodeInstance extends StateBasedNodeInstance implements EventListener { + private static final Logger logger = LoggerFactory.getLogger(TimerNodeInstance.class); private static final long serialVersionUID = 510l; public static final String TIMER_TRIGGERED_EVENT = "timerTriggered"; @@ -111,13 +117,21 @@ public String[] getEventTypes() { @Override public void triggerCompleted(boolean remove) { - triggerCompleted(Node.CONNECTION_DEFAULT_TYPE, remove); + Exception e = new WorkItemExecutionException("TimedOut"); + ExceptionScopeInstance esi = (ExceptionScopeInstance) resolveContextInstance(ExceptionScope.EXCEPTION_SCOPE, e); + if (esi != null) { + logger.debug("Triggering exception handler for {}", e.getClass().getName()); + esi.handleException(e, getProcessContext(e)); + } else { + logger.trace("No exception handler for {}", e.getClass().getName()); + triggerCompleted(Node.CONNECTION_DEFAULT_TYPE, remove); + } } @Override - public void cancel() { + public void cancel(CancelType cancelType) { ((InternalProcessRuntime) getProcessInstance().getKnowledgeRuntime().getProcessRuntime()).getJobsService().cancelJob(timerId); - super.cancel(); + super.cancel(cancelType); } @Override diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java index 5d7c6250302..a2399fba1fb 100755 --- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java +++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.UUID; import java.util.function.Function; import org.drools.core.WorkItemHandlerNotFoundException; @@ -104,11 +105,15 @@ protected WorkItemNode getWorkItemNode() { @Override public InternalKogitoWorkItem getWorkItem() { if (workItem == null && workItemId != null) { - workItem = ((InternalKogitoWorkItemManager) getProcessInstance().getKnowledgeRuntime().getWorkItemManager()).getWorkItem(workItemId); + workItem = decorate(((InternalKogitoWorkItemManager) getProcessInstance().getKnowledgeRuntime().getWorkItemManager()).getWorkItem(workItemId)); } return workItem; } + protected InternalKogitoWorkItem decorate(InternalKogitoWorkItem kogitoWorkItem) { + return kogitoWorkItem; + } + public String getWorkItemId() { return workItemId; } @@ -118,7 +123,7 @@ public void internalSetWorkItemId(String workItemId) { } public void internalSetWorkItem(InternalKogitoWorkItem workItem) { - this.workItem = workItem; + this.workItem = decorate(workItem); this.workItem.setProcessInstance(getProcessInstance()); this.workItem.setNodeInstance(this); } @@ -157,7 +162,8 @@ public void internalTrigger(final KogitoNodeInstance from, String type) { workItem.setProcessInstance(getProcessInstance()); if (workItemNode.getWork().getWorkParametersFactory() != null) { - workItem.getParameters().putAll(workItemNode.getWork().getWorkParametersFactory().apply(workItem)); + Map parameters = workItemNode.getWork().getWorkParametersFactory().apply(workItem); + parameters.forEach(workItem::setParameter); } processWorkItemHandler(() -> ((InternalKogitoWorkItemManager) InternalProcessRuntime.asKogitoProcessRuntime(getProcessInstance().getKnowledgeRuntime()).getKogitoWorkItemManager()) @@ -216,8 +222,14 @@ protected InternalKogitoWorkItem newWorkItem() { protected InternalKogitoWorkItem createWorkItem(WorkItemNode workItemNode) { Work work = workItemNode.getWork(); workItem = newWorkItem(); + workItem.setId(UUID.randomUUID().toString()); workItem.setName(work.getName()); workItem.setProcessInstanceId(getProcessInstance().getStringId()); + workItem.setProcessInstance(this.getKogitoProcessInstance()); + workItem.setNodeInstance(this); + workItem.setNodeInstanceId(this.getId()); + workItem.setStartDate(new Date()); + Map resolvedParameters = new HashMap<>(); Collection metaParameters = work.getMetaParameters(); @@ -237,8 +249,6 @@ protected InternalKogitoWorkItem createWorkItem(WorkItemNode workItemNode) { } } - workItem.setStartDate(new Date()); - Function varResolver = (varRef) -> { if (resolvedParameters.containsKey(varRef)) { return resolvedParameters.get(varRef); @@ -251,7 +261,8 @@ protected InternalKogitoWorkItem createWorkItem(WorkItemNode workItemNode) { if (dynamicParameters != null) { inputSet.putAll(dynamicParameters); } - workItem.getParameters().putAll(inputSet); + + inputSet.forEach(workItem::setParameter); return workItem; } @@ -277,7 +288,7 @@ public void triggerCompleted(InternalKogitoWorkItem workItem) { } @Override - public void cancel() { + public void cancel(CancelType cancelType) { InternalKogitoWorkItem item = getWorkItem(); if (item != null && item.getState() != COMPLETED && item.getState() != ABORTED) { try { @@ -295,7 +306,7 @@ public void cancel() { processInstance.setState(STATE_ABORTED); } } - super.cancel(); + super.cancel(cancelType); } @Override diff --git a/jbpm/process-serialization-protobuf/src/main/java/org/kie/kogito/serialization/process/impl/ProtobufProcessInstanceReader.java b/jbpm/process-serialization-protobuf/src/main/java/org/kie/kogito/serialization/process/impl/ProtobufProcessInstanceReader.java index 1946febc6b0..a7581dc555e 100644 --- a/jbpm/process-serialization-protobuf/src/main/java/org/kie/kogito/serialization/process/impl/ProtobufProcessInstanceReader.java +++ b/jbpm/process-serialization-protobuf/src/main/java/org/kie/kogito/serialization/process/impl/ProtobufProcessInstanceReader.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; @@ -38,6 +39,7 @@ import org.jbpm.process.instance.context.swimlane.SwimlaneContextInstance; import org.jbpm.process.instance.context.variable.VariableScopeInstance; import org.jbpm.process.instance.impl.humantask.HumanTaskWorkItemImpl; +import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem; import org.jbpm.process.instance.impl.humantask.Reassignment; import org.jbpm.ruleflow.instance.RuleFlowProcessInstance; import org.jbpm.workflow.core.node.AsyncEventNodeInstance; @@ -61,6 +63,7 @@ import org.kie.kogito.process.impl.AbstractProcess; import org.kie.kogito.process.workitem.Attachment; import org.kie.kogito.process.workitem.Comment; +import org.kie.kogito.process.workitems.InternalKogitoWorkItem; import org.kie.kogito.process.workitems.impl.KogitoWorkItemImpl; import org.kie.kogito.serialization.process.MarshallerContextName; import org.kie.kogito.serialization.process.MarshallerReaderContext; @@ -451,7 +454,7 @@ private NodeInstanceImpl buildWorkItemNodeInstance(WorkItemNodeInstanceContent c WorkItemNodeInstance nodeInstance = instanceWorkItem(content); if (nodeInstance instanceof HumanTaskNodeInstance) { HumanTaskNodeInstance humanTaskNodeInstance = (HumanTaskNodeInstance) nodeInstance; - HumanTaskWorkItemImpl workItem = (HumanTaskWorkItemImpl) nodeInstance.getWorkItem(); + InternalHumanTaskWorkItem workItem = humanTaskNodeInstance.getWorkItem(); Any workItemDataMessage = content.getWorkItemData(); if (workItemDataMessage.is(HumanTaskWorkItemData.class)) { HumanTaskWorkItemData workItemData = workItemDataMessage.unpack(HumanTaskWorkItemData.class); @@ -488,7 +491,7 @@ private NodeInstanceImpl buildWorkItemNodeInstance(WorkItemNodeInstanceContent c } nodeInstance.internalSetWorkItemId(content.getWorkItemId()); - KogitoWorkItemImpl workItem = (KogitoWorkItemImpl) nodeInstance.getWorkItem(); + InternalKogitoWorkItem workItem = (InternalKogitoWorkItem) nodeInstance.getWorkItem(); workItem.setId(content.getWorkItemId()); workItem.setProcessInstanceId(ruleFlowProcessInstance.getStringId()); workItem.setName(content.getName()); @@ -531,6 +534,7 @@ private WorkItemNodeInstance instanceWorkItem(WorkItemNodeInstanceContent conten } else { WorkItemNodeInstance nodeInstance = new WorkItemNodeInstance(); KogitoWorkItemImpl workItem = new KogitoWorkItemImpl(); + workItem.setId(UUID.randomUUID().toString()); nodeInstance.internalSetWorkItem(workItem); return nodeInstance; } diff --git a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/InternalKogitoWorkItem.java b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/InternalKogitoWorkItem.java index d4f9151a8b3..e1bbb25614e 100755 --- a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/InternalKogitoWorkItem.java +++ b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/InternalKogitoWorkItem.java @@ -42,4 +42,8 @@ public interface InternalKogitoWorkItem extends org.drools.core.process.WorkItem void setNodeInstance(KogitoNodeInstance nodeInstance); void setProcessInstance(KogitoProcessInstance processInstance); + + void setResult(String name, Object value); + + void setId(String string); } diff --git a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoDefaultWorkItemManager.java b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoDefaultWorkItemManager.java index 458c2976435..46635608971 100755 --- a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoDefaultWorkItemManager.java +++ b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoDefaultWorkItemManager.java @@ -24,7 +24,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -40,8 +39,8 @@ import org.kie.kogito.process.workitems.InternalKogitoWorkItemManager; import org.kie.kogito.process.workitems.KogitoWorkItemHandlerNotFoundException; -import static org.kie.kogito.internal.process.runtime.KogitoWorkItem.ABORTED; -import static org.kie.kogito.internal.process.runtime.KogitoWorkItem.COMPLETED; +import static org.kie.api.runtime.process.WorkItem.ABORTED; +import static org.kie.api.runtime.process.WorkItem.COMPLETED; public class KogitoDefaultWorkItemManager implements InternalKogitoWorkItemManager { @@ -61,7 +60,6 @@ public void writeExternal(ObjectOutput out) throws IOException { @Override public void internalExecuteWorkItem(InternalKogitoWorkItem workItem) { - ((KogitoWorkItemImpl) workItem).setId(UUID.randomUUID().toString()); internalAddWorkItem(workItem); KogitoWorkItemHandler handler = this.workItemHandlers.get(workItem.getName()); if (handler != null) { @@ -82,7 +80,7 @@ public void internalRemoveWorkItem(String id) { @Override public void internalAbortWorkItem(String id) { - KogitoWorkItemImpl workItem = (KogitoWorkItemImpl) workItems.get(id); + InternalKogitoWorkItem workItem = workItems.get(id); // work item may have been aborted if (workItem != null) { KogitoWorkItemHandler handler = this.workItemHandlers.get(workItem.getName()); @@ -144,7 +142,7 @@ public void completeWorkItem(String id, Map results, Policy.. @Override public void abortWorkItem(String id, Policy... policies) { - KogitoWorkItemImpl workItem = (KogitoWorkItemImpl) workItems.get(id); + InternalKogitoWorkItem workItem = workItems.get(id); // work item may have been aborted if (workItem != null) { KogitoProcessInstance processInstance = kruntime.getProcessInstance(workItem.getProcessInstanceStringId()); diff --git a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java index 1eae6cb370b..884cc421d10 100755 --- a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java +++ b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/KogitoWorkItemImpl.java @@ -115,6 +115,7 @@ public void setResults(Map results) { } } + @Override public void setResult(String name, Object value) { results.put(name, value); } diff --git a/kogito-build/kogito-build-no-bom-parent/pom.xml b/kogito-build/kogito-build-no-bom-parent/pom.xml index f09e9357eb3..5220822064e 100644 --- a/kogito-build/kogito-build-no-bom-parent/pom.xml +++ b/kogito-build/kogito-build-no-bom-parent/pom.xml @@ -116,7 +116,7 @@ 3.0.5 2.5.2 3.2.2 - 0.8.5 + 0.8.11 io.smallrye 3.0.5 3.1.0 @@ -144,6 +144,9 @@ 2.5 1.0.1 1.5 + + + 3.3.0 @@ -181,7 +184,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - ${version.checkstyle.plugin} + ${version.maven-checkstyle} @@ -332,7 +335,7 @@ maven-failsafe-plugin - ${version.failsafe.plugin} + ${version.maven-surefire} integration-test @@ -468,6 +471,7 @@ ${skipTests} true ${project.build.directory}/it + true diff --git a/kogito-build/kogito-dependencies-bom/pom.xml b/kogito-build/kogito-dependencies-bom/pom.xml index b5586ee40a8..7d14735217c 100644 --- a/kogito-build/kogito-dependencies-bom/pom.xml +++ b/kogito-build/kogito-dependencies-bom/pom.xml @@ -16,7 +16,7 @@ - 2.16.10.Final + 2.16.12.Final ${version.io.quarkus} 2.6.6 3.4.0 @@ -29,7 +29,7 @@ 2.4.10 1.0.0-preview.20220705 1.1.0 - 1.3.9 + 1.3.14 0.0.6 1.1.5 0.0.9 @@ -59,7 +59,7 @@ 1.10.2 9.8.3 42.5.1 - 4.0.4.Final + 4.0.5.Final 3.1.1 4.2.0 @@ -71,7 +71,8 @@ 2.15.0 - 2.0.26 + 2.1.16 + 2.2.14 3.12.0 @@ -125,6 +126,7 @@ 1.0-1 4.1.1 32.0.1-jre + 1.24.0 @@ -135,6 +137,13 @@ guava ${version.com.google.guava} + + + org.apache.commons + commons-compress + ${version.apache.commons.commons-compress} + + org.slf4j slf4j-api @@ -612,6 +621,18 @@ swagger-parser ${version.io.swagger.parser.v3} + + + io.swagger.core.v3 + swagger-model + ${version.io.swagger.core.v3} + + + + io.swagger.core.v3 + swagger-core + ${version.io.swagger.core.v3} + diff --git a/kogito-build/kogito-kie-bom/pom.xml b/kogito-build/kogito-kie-bom/pom.xml index 715dbf66c83..a900ed54a3f 100644 --- a/kogito-build/kogito-kie-bom/pom.xml +++ b/kogito-build/kogito-kie-bom/pom.xml @@ -192,7 +192,7 @@ org.drools - drools-drl-quarkus-util-deployment + drools-quarkus-util-deployment ${version.org.kie} diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/KogitoBuildContext.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/KogitoBuildContext.java index 48406f10ab2..5bb7f95dc75 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/KogitoBuildContext.java +++ b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/KogitoBuildContext.java @@ -30,13 +30,13 @@ import org.drools.codegen.common.AppPaths; import org.drools.codegen.common.DroolsModelBuildContext; +import org.drools.codegen.common.di.DependencyInjectionAnnotator; +import org.drools.codegen.common.rest.RestAnnotator; import org.kie.kogito.KogitoGAV; import org.kie.kogito.codegen.api.AddonsConfig; import org.kie.kogito.codegen.api.ApplicationSection; import org.kie.kogito.codegen.api.Generator; import org.kie.kogito.codegen.api.SourceFileCodegenBindNotifier; -import org.kie.kogito.codegen.api.di.DependencyInjectionAnnotator; -import org.kie.kogito.codegen.api.rest.RestAnnotator; import org.kie.kogito.codegen.api.utils.KogitoCodeGenConstants; public interface KogitoBuildContext extends DroolsModelBuildContext { @@ -49,11 +49,6 @@ static String generateRESTConfigurationKeyForResource(String generatorType) { boolean hasImplementationClassAvailable(Class clazz); - /** - * Return DependencyInjectionAnnotator if available or null - */ - DependencyInjectionAnnotator getDependencyInjectionAnnotator(); - /** * Method to override default dependency injection annotator */ @@ -69,11 +64,6 @@ default boolean hasDI() { "true".equalsIgnoreCase(getApplicationProperty(KOGITO_GENERATE_DI).orElse("true")); } - /** - * Return RestAnnotator if available or null - */ - RestAnnotator getRestAnnotator(); - /** * Method to override default REST annotator */ diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContext.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContext.java index 75242cf28ae..25a0e8794da 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContext.java +++ b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContext.java @@ -37,14 +37,14 @@ import javax.lang.model.SourceVersion; import org.drools.codegen.common.AppPaths; +import org.drools.codegen.common.di.DependencyInjectionAnnotator; +import org.drools.codegen.common.rest.RestAnnotator; import org.kie.kogito.KogitoGAV; import org.kie.kogito.codegen.api.AddonsConfig; import org.kie.kogito.codegen.api.ApplicationSection; import org.kie.kogito.codegen.api.SourceFileCodegenBindNotifier; import org.kie.kogito.codegen.api.context.KogitoApplicationPropertyProvider; import org.kie.kogito.codegen.api.context.KogitoBuildContext; -import org.kie.kogito.codegen.api.di.DependencyInjectionAnnotator; -import org.kie.kogito.codegen.api.rest.RestAnnotator; import org.kie.kogito.codegen.api.utils.AddonsConfigDiscovery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/JavaKogitoBuildContext.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/JavaKogitoBuildContext.java index e0c549332be..2af68b401e3 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/JavaKogitoBuildContext.java +++ b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/JavaKogitoBuildContext.java @@ -30,6 +30,11 @@ public static Builder builder() { return new JavaKogitoBuildContextBuilder(); } + @Override + public boolean hasRest() { + return false; + } + protected static class JavaKogitoBuildContextBuilder extends AbstractBuilder { protected JavaKogitoBuildContextBuilder() { diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/QuarkusKogitoBuildContext.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/QuarkusKogitoBuildContext.java index 9a888b9c4e8..a8452706640 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/QuarkusKogitoBuildContext.java +++ b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/QuarkusKogitoBuildContext.java @@ -18,8 +18,8 @@ */ package org.kie.kogito.codegen.api.context.impl; -import org.kie.kogito.codegen.api.di.impl.CDIDependencyInjectionAnnotator; -import org.kie.kogito.codegen.api.rest.impl.CDIRestAnnotator; +import org.drools.codegen.common.di.impl.CDIDependencyInjectionAnnotator; +import org.drools.codegen.common.rest.impl.CDIRestAnnotator; public class QuarkusKogitoBuildContext extends AbstractKogitoBuildContext { @@ -35,6 +35,11 @@ public static Builder builder() { return new QuarkusKogitoBuildContextBuilder(); } + @Override + public boolean hasRest() { + return hasClassAvailable(QUARKUS_REST); + } + protected static class QuarkusKogitoBuildContextBuilder extends AbstractBuilder { protected QuarkusKogitoBuildContextBuilder() { diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/SpringBootKogitoBuildContext.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/SpringBootKogitoBuildContext.java index ddb5da3657a..baa4fc4863c 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/SpringBootKogitoBuildContext.java +++ b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/context/impl/SpringBootKogitoBuildContext.java @@ -18,8 +18,8 @@ */ package org.kie.kogito.codegen.api.context.impl; -import org.kie.kogito.codegen.api.di.impl.SpringDependencyInjectionAnnotator; -import org.kie.kogito.codegen.api.rest.impl.SpringRestAnnotator; +import org.drools.codegen.common.di.impl.SpringDependencyInjectionAnnotator; +import org.drools.codegen.common.rest.impl.SpringRestAnnotator; public class SpringBootKogitoBuildContext extends AbstractKogitoBuildContext { @@ -35,6 +35,11 @@ public static Builder builder() { return new SpringBootKogitoBuildContextBuilder(); } + @Override + public boolean hasRest() { + return hasClassAvailable(SPRING_REST); + } + protected static class SpringBootKogitoBuildContextBuilder extends AbstractBuilder { protected SpringBootKogitoBuildContextBuilder() { diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/DependencyInjectionAnnotator.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/DependencyInjectionAnnotator.java deleted file mode 100644 index 54db9585211..00000000000 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/DependencyInjectionAnnotator.java +++ /dev/null @@ -1,270 +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.codegen.api.di; - -import java.util.ArrayList; -import java.util.List; - -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.expr.ArrayInitializerExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MemberValuePair; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.Name; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; - -/** - * Generic abstraction for dependency injection annotations that allow to - * use different frameworks based needs. - *

- * Currently in scope - * - *

    - *
  • CDI
  • - *
  • Spring
  • - *
- */ -public interface DependencyInjectionAnnotator { - - /** - * Annotates the given node with an annotation to produce a DI instance of the node target class, e.g. Produces, - * Bean. This is used by configuration classes in the DI, like a factory method. - * - * @param node - * @param isDefault indicates if the bean instance is created only if there are not any other bean of this type - * already declared in the application, e.g DefaultBean - */ - > T withProduces(T node, boolean isDefault); - - /** - * Annotates given node with name annotation e.g. Named, Qualifier - * - * @param node node to be annotated - */ - > T withNamed(T node, String name); - - /** - * Annotates given node with application level annotations e.g. ApplicationScoped, Component - * - * @param node node to be annotated - */ - > T withApplicationComponent(T node); - - /** - * Annotates given node with application level annotations e.g. ApplicationScoped, Component - * additionally adding name to it - * - * @param node node to be annotated - * @param name name to be assigned to given node - */ - > T withNamedApplicationComponent(T node, String name); - - /** - * Annotates given node with singleton level annotations e.g. Singleton, Component - * - * @param node node to be annotated - */ - > T withSingletonComponent(T node); - - /** - * Annotates given node with singleton level annotations e.g. Singleton, Component - * additionally adding name to it - * - * @param node node to be annotated - * @param name name to be assigned to given node - */ - > T withNamedSingletonComponent(T node, String name); - - /** - * Annotates given node with injection annotations e.g. Inject, Autowire - * - * @param node node to be annotated - * @boolean forceLazyInit use lazy initialization (for those container that applies) - */ - > T withInjection(T node, boolean forceLazyInit); - - /** - * Annotates given node with injection annotations e.g. Inject, Autowire - * - * @param node node to be annotated - */ - default > T withInjection(T node) { - return withInjection(node, false); - } - - /** - * Annotates given node with injection annotations e.g. Inject, Autowire - * additionally adding name to it - * - * @param node node to be annotated - * @param name name to be assigned to given node - */ - > T withNamedInjection(T node, String name); - - /** - * Annotates given node with optional injection annotations e.g. Inject, Autowire - * - * @param node node to be annotated - */ - > T withOptionalInjection(T node); - - /** - * Annotates given node with incoming message that it should consume from - * - * @param node node to be annotated - * @param channel name of the channel messages should be consumer from - */ - > T withIncomingMessage(T node, String channel); - - /** - * Annotates given node with outgoing message that it should send to - * - * @param node node to be annotated - * @param channel name of the channel messages should be send to - */ - > T withOutgoingMessage(T node, String channel); - - /** - * Annotates given node with configuration parameter injection - * - * @param node node to be annotated - * @param configKey name of the configuration property to be injected - */ - > T withConfigInjection(T node, String configKey); - - /** - * Annotates given node with configuration parameter injection with default value - * - * @param node node to be annotated - * @param configKey name of the configuration property to be injected - * @param defaultValue value to be used in case there is no config parameter defined - */ - > T withConfigInjection(T node, String configKey, String defaultValue); - - /** - * Annotates and enhances method used to produce messages - * - * @param produceMethod method to be annotated - * @param channel channel on which messages should be produced - * @param event actual data to be send - */ - MethodCallExpr withMessageProducer(MethodCallExpr produceMethod, String channel, Expression event); - - /** - * Annotates given node with set of roles to enforce security - * - * @param node node to be annotated - * @param roles roles that are allowed - */ - default > T withSecurityRoles(T node, String[] roles) { - if (roles != null && roles.length > 0) { - List rolesExpr = new ArrayList<>(); - - for (String role : roles) { - rolesExpr.add(new StringLiteralExpr(role.trim())); - } - - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("javax.annotation.security.RolesAllowed"), new ArrayInitializerExpr(NodeList.nodeList(rolesExpr)))); - } - return node; - } - - /** - * Returns type that allows to inject optional instances of the same type - * - * @return fully qualified class name - */ - String optionalInstanceInjectionType(); - - /** - * Creates an expression that represents optional instance for given field - * - * @param fieldName name of the field that should be considered optional - * @return complete expression for optional instance - */ - Expression optionalInstanceExists(String fieldName); - - /** - * Creates an expression that returns instance for given optional field - * - * @param fieldName name of the optional field that should be accessed - * @return complete expression for optional instance - */ - default Expression getOptionalInstance(String fieldName) { - return new MethodCallExpr(new NameExpr(fieldName), "get"); - } - - /** - * Returns type that allows to inject multiple instances of the same type - * - * @return fully qualified class name - */ - String multiInstanceInjectionType(); - - /** - * Creates an expression that returns a list of instances for given multi instance field - * - * @param fieldName name of the multi field that should be accessed - * @return complete expression for multi instance - */ - Expression getMultiInstance(String fieldName); - - /** - * Returns type that allows to mark instance as application component e.g. ApplicationScoped, Component - * - * @return fully qualified class name - */ - String applicationComponentType(); - - /** - * Returns type to be used as message emitter - * - * @param dataType type of the data produces by the emitter - * @return fully qualified class name - */ - String emitterType(String dataType); - - /** - * Annotates given node with a initializing annotation e.g. Startup - * - * @param node node to be annotated - */ - > T withEagerStartup(T node); - - /** - * Annotates given node with factory class annotations e.g. Configuration for Spring Boot - * - * @param node node to be annotated - */ - > T withFactoryClass(T node); - - /** - * Annotates given node with factory method annotations e.g. Produces, Bean - * - * @param node node to be annotated - */ - > T withFactoryMethod(T node); - - default > T withTagAnnotation(T node, NodeList attributes) { - return node; - } -} diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/impl/CDIDependencyInjectionAnnotator.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/impl/CDIDependencyInjectionAnnotator.java deleted file mode 100644 index c95e834bb08..00000000000 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/impl/CDIDependencyInjectionAnnotator.java +++ /dev/null @@ -1,187 +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.codegen.api.di.impl; - -import org.kie.kogito.codegen.api.di.DependencyInjectionAnnotator; - -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.expr.BinaryExpr; -import com.github.javaparser.ast.expr.BooleanLiteralExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MemberValuePair; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.Name; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.NormalAnnotationExpr; -import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; - -public class CDIDependencyInjectionAnnotator implements DependencyInjectionAnnotator { - - @Override - public > T withProduces(T node, boolean isDefault) { - node.addAndGetAnnotation("javax.enterprise.inject.Produces"); - if (isDefault) { - node.addAndGetAnnotation("io.quarkus.arc.DefaultBean"); - } - return node; - } - - @Override - public > T withNamed(T node, String name) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("javax.inject.Named"), new StringLiteralExpr(name))); - return node; - } - - @Override - public > T withApplicationComponent(T node) { - node.addAnnotation("javax.enterprise.context.ApplicationScoped"); - return node; - } - - @Override - public > T withNamedApplicationComponent(T node, String name) { - return withNamed(withApplicationComponent(node), name); - } - - @Override - public > T withSingletonComponent(T node) { - node.addAnnotation("javax.inject.Singleton"); - return node; - } - - @Override - public > T withNamedSingletonComponent(T node, String name) { - return withNamed(withSingletonComponent(node), name); - } - - @Override - public > T withInjection(T node, boolean lazy) { - node.addAnnotation("javax.inject.Inject"); - return node; - } - - @Override - public > T withNamedInjection(T node, String name) { - return withNamed(withInjection(node), name); - } - - @Override - public > T withOptionalInjection(T node) { - return withInjection(node); - } - - @Override - public > T withIncomingMessage(T node, String channel) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("org.eclipse.microprofile.reactive.messaging.Incoming"), new StringLiteralExpr(channel))); - return node; - } - - @Override - public > T withOutgoingMessage(T node, String channel) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("org.eclipse.microprofile.reactive.messaging.Channel"), new StringLiteralExpr(channel))); - return node; - } - - @Override - public MethodCallExpr withMessageProducer(MethodCallExpr produceMethod, String channel, Expression event) { - produceMethod.addArgument(event); - return produceMethod; - } - - @Override - public String optionalInstanceInjectionType() { - return "javax.enterprise.inject.Instance"; - } - - @Override - public Expression optionalInstanceExists(String fieldName) { - MethodCallExpr condition = new MethodCallExpr(new NameExpr(fieldName), "isUnsatisfied"); - return new BinaryExpr(condition, new BooleanLiteralExpr(false), BinaryExpr.Operator.EQUALS); - } - - @Override - public String multiInstanceInjectionType() { - return optionalInstanceInjectionType(); - } - - @Override - public Expression getMultiInstance(String fieldName) { - return new MethodCallExpr( - new MethodCallExpr(new NameExpr("java.util.stream.StreamSupport"), "stream", NodeList.nodeList( - new MethodCallExpr(new NameExpr(fieldName), "spliterator"), - new BooleanLiteralExpr(false))), - "collect", - NodeList.nodeList( - new MethodCallExpr(new NameExpr("java.util.stream.Collectors"), "toList"))); - } - - @Override - public String applicationComponentType() { - return "javax.enterprise.context.ApplicationScoped"; - } - - @Override - public String emitterType(String dataType) { - return "org.eclipse.microprofile.reactive.messaging.Emitter<" + dataType + ">"; - } - - @Override - public > T withConfigInjection(T node, String configKey) { - node.addAnnotation(new NormalAnnotationExpr( - new Name("org.eclipse.microprofile.config.inject.ConfigProperty"), - NodeList.nodeList( - new MemberValuePair("name", new StringLiteralExpr(configKey))))); - return node; - } - - @Override - public > T withConfigInjection(T node, String configKey, String defaultValue) { - node.addAnnotation(new NormalAnnotationExpr( - new Name("org.eclipse.microprofile.config.inject.ConfigProperty"), - NodeList.nodeList( - new MemberValuePair("name", new StringLiteralExpr(configKey)), - new MemberValuePair("defaultValue", new StringLiteralExpr(defaultValue))))); - return node; - } - - @Override - public > T withEagerStartup(T node) { - node.addAnnotation("io.quarkus.runtime.Startup"); - return node; - } - - @Override - public > T withFactoryClass(T node) { - return node; - } - - @Override - public > T withFactoryMethod(T node) { - node.addAnnotation("javax.enterprise.inject.Produces"); - return node; - } - - @Override - public > T withTagAnnotation(T node, NodeList attributes) { - node.addAnnotation(new NormalAnnotationExpr(new Name("org.eclipse.microprofile.openapi.annotations.tags.Tag"), attributes)); - return node; - } -} diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/impl/SpringDependencyInjectionAnnotator.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/impl/SpringDependencyInjectionAnnotator.java deleted file mode 100644 index 7cdeeece4b7..00000000000 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/di/impl/SpringDependencyInjectionAnnotator.java +++ /dev/null @@ -1,190 +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.codegen.api.di.impl; - -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; - -import org.kie.kogito.codegen.api.di.DependencyInjectionAnnotator; - -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.expr.BinaryExpr; -import com.github.javaparser.ast.expr.BooleanLiteralExpr; -import com.github.javaparser.ast.expr.ConditionalExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MemberValuePair; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.Name; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.NormalAnnotationExpr; -import com.github.javaparser.ast.expr.NullLiteralExpr; -import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.expr.TypeExpr; -import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; -import com.github.javaparser.ast.type.ClassOrInterfaceType; - -public class SpringDependencyInjectionAnnotator implements DependencyInjectionAnnotator { - - @Override - public > T withProduces(T node, boolean isDefault) { - node.addAnnotation("org.springframework.context.annotation.Bean"); - if (isDefault) { - node.addAnnotation("org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean"); - } - return node; - } - - @Override - public > T withNamed(T node, String name) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("org.springframework.beans.factory.annotation.Qualifier"), new StringLiteralExpr(name))); - return node; - } - - @Override - public > T withApplicationComponent(T node) { - node.addAnnotation("org.springframework.stereotype.Component"); - return node; - } - - @Override - public > T withNamedApplicationComponent(T node, String name) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("org.springframework.stereotype.Component"), new StringLiteralExpr(name))); - return node; - } - - @Override - public > T withSingletonComponent(T node) { - return withApplicationComponent(node); - } - - @Override - public > T withNamedSingletonComponent(T node, String name) { - return withNamedApplicationComponent(node, name); - } - - @Override - public > T withInjection(T node, boolean lazy) { - node.addAnnotation("org.springframework.beans.factory.annotation.Autowired"); - if (lazy) { - node.addAnnotation("org.springframework.context.annotation.Lazy"); - } - return node; - } - - @Override - public > T withNamedInjection(T node, String name) { - return withNamed(withInjection(node), name); - } - - @Override - public > T withOptionalInjection(T node) { - node.addAnnotation( - new NormalAnnotationExpr(new Name("org.springframework.beans.factory.annotation.Autowired"), NodeList.nodeList(new MemberValuePair("required", new BooleanLiteralExpr(false))))); - node.addAnnotation("org.springframework.context.annotation.Lazy"); - return node; - } - - @Override - public > T withIncomingMessage(T node, String channel) { - node.addAnnotation(new NormalAnnotationExpr(new Name("org.springframework.kafka.annotation.KafkaListener"), NodeList.nodeList(new MemberValuePair("topics", new StringLiteralExpr(channel))))); - return node; - } - - @Override - public > T withOutgoingMessage(T node, String channel) { - // currently no-op - return node; - } - - @Override - public MethodCallExpr withMessageProducer(MethodCallExpr produceMethod, String channel, Expression event) { - produceMethod.addArgument(new StringLiteralExpr(channel)).addArgument(event); - return produceMethod; - } - - @Override - public String optionalInstanceInjectionType() { - return Optional.class.getCanonicalName(); - } - - @Override - public Expression optionalInstanceExists(String fieldName) { - return new MethodCallExpr(new NameExpr(fieldName), "isPresent"); - } - - @Override - public String multiInstanceInjectionType() { - return Collection.class.getCanonicalName(); - } - - @Override - public Expression getMultiInstance(String fieldName) { - return new ConditionalExpr( - new BinaryExpr(new NameExpr(fieldName), new NullLiteralExpr(), BinaryExpr.Operator.NOT_EQUALS), - new NameExpr(fieldName), - new MethodCallExpr(new TypeExpr(new ClassOrInterfaceType(null, Collections.class.getCanonicalName())), "emptyList")); - } - - @Override - public String applicationComponentType() { - return "org.springframework.stereotype.Component"; - } - - @Override - public String emitterType(String dataType) { - return "org.springframework.kafka.core.KafkaTemplate"; - } - - @Override - public > T withConfigInjection(T node, String configKey) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("org.springframework.beans.factory.annotation.Value"), new StringLiteralExpr("${" + configKey + ":#{null}}"))); - return node; - } - - @Override - public > T withConfigInjection(T node, String configKey, String defaultValue) { - node.addAnnotation(new SingleMemberAnnotationExpr(new Name("org.springframework.beans.factory.annotation.Value"), new StringLiteralExpr("${" + configKey + ":" + defaultValue + "}"))); - return node; - } - - /** - * no-op, Spring beans are not lazy by default. - * - * @param node node to be annotated - * @return - */ - @Override - public > T withEagerStartup(T node) { - return node; - } - - @Override - public > T withFactoryClass(T node) { - node.addAnnotation("org.springframework.context.annotation.Configuration"); - return node; - } - - @Override - public > T withFactoryMethod(T node) { - node.addAnnotation("org.springframework.context.annotation.Bean"); - return node; - } -} diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/impl/CDIRestAnnotator.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/impl/CDIRestAnnotator.java deleted file mode 100644 index 66fecd0f80d..00000000000 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/impl/CDIRestAnnotator.java +++ /dev/null @@ -1,43 +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.codegen.api.rest.impl; - -import java.util.Optional; -import java.util.stream.Stream; - -import org.kie.kogito.codegen.api.rest.RestAnnotator; - -import com.github.javaparser.ast.expr.AnnotationExpr; -import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; - -public class CDIRestAnnotator implements RestAnnotator { - - @Override - public > boolean isRestAnnotated(T node) { - return Stream.of("POST", "GET", "PUT", "DELETE") - .map(node::getAnnotationByName) - .anyMatch(Optional::isPresent); - } - - @Override - public > Optional getEndpointValue(T node) { - Optional path = node.getAnnotationByName("Path"); - return path.map(annotationExpr -> annotationExpr.asSingleMemberAnnotationExpr().getMemberValue().asStringLiteralExpr().asString()); - } -} diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/impl/SpringRestAnnotator.java b/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/impl/SpringRestAnnotator.java deleted file mode 100644 index e9dfe39361b..00000000000 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/impl/SpringRestAnnotator.java +++ /dev/null @@ -1,48 +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.codegen.api.rest.impl; - -import java.util.Optional; -import java.util.stream.Stream; - -import org.kie.kogito.codegen.api.rest.RestAnnotator; - -import com.github.javaparser.ast.expr.AnnotationExpr; -import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; - -public class SpringRestAnnotator implements RestAnnotator { - - @Override - public > boolean isRestAnnotated(T node) { - return Stream.of("PostMapping", "GetMapping", "PutMapping", "DeleteMapping") - .map(node::getAnnotationByName) - .anyMatch(Optional::isPresent); - } - - @Override - public > Optional getEndpointValue(T node) { - Optional path = node.getAnnotationByName("PostMapping"); - return path - .flatMap(p -> p.asNormalAnnotationExpr() - .getPairs() - .stream() - .filter(x -> "value".equals(x.getName().asString())).findFirst()) - .map(value -> value.getValue().asStringLiteralExpr().asString()); - } -} diff --git a/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContextTest.java b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContextTest.java index c41878539a2..61b4e50dfa7 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContextTest.java +++ b/kogito-codegen-modules/kogito-codegen-api/src/test/java/org/kie/kogito/codegen/api/context/impl/AbstractKogitoBuildContextTest.java @@ -97,6 +97,11 @@ protected MockKogitoBuildContext(MockKogiotBuildContextBuilder builder) { super(builder, null, null, "Mock"); } + @Override + public boolean hasRest() { + return false; + } + public static class MockKogiotBuildContextBuilder extends AbstractKogitoBuildContext.AbstractBuilder { protected MockKogiotBuildContextBuilder() { diff --git a/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceQuarkusTemplate.java index 57d3dfcc692..bc71d6ad53e 100644 --- a/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceQuarkusTemplate.java +++ b/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceQuarkusTemplate.java @@ -18,6 +18,8 @@ */ package org.kie.dmn.kogito.quarkus.example; +import java.io.InputStream; +import java.util.Objects; import java.util.stream.Collectors; import javax.ws.rs.Consumes; @@ -29,6 +31,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; +import org.kie.dmn.feel.codegen.feel11.CodegenStringUtil; import org.kie.kogito.Application; import org.kie.kogito.dmn.rest.DMNEvaluationErrorException; import org.kie.kogito.dmn.rest.DMNJSONUtils; @@ -70,10 +73,9 @@ public Response dmn($inputType$ variables) { @GET @Produces(MediaType.APPLICATION_XML) public String dmn() throws java.io.IOException { - return new String(org.drools.util.IoUtils. - readBytesFromInputStream(this.getClass() - .getResourceAsStream(org.kie.dmn.feel.codegen.feel11.CodegenStringUtil.escapeIdentifier("$modelName$") + - ".dmn_nologic"))); + try (InputStream is = this.getClass().getResourceAsStream(CodegenStringUtil.escapeIdentifier("$modelName$") + ".dmn_nologic")) { + return new String(org.drools.util.IoUtils.readBytesFromInputStream(Objects.requireNonNull(is))); + } } private ResponseBuilder extractContextIfSucceded(KogitoDMNResult result){ diff --git a/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceSpringTemplate.java index 2bf855cb9c8..27bfc5a33a7 100644 --- a/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceSpringTemplate.java +++ b/kogito-codegen-modules/kogito-codegen-decisions/src/main/resources/class-templates/DecisionRestResourceSpringTemplate.java @@ -18,10 +18,13 @@ */ package org.kie.dmn.kogito.quarkus.example; +import java.io.InputStream; import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; +import java.util.Objects; import java.util.stream.Collectors; +import org.kie.dmn.feel.codegen.feel11.CodegenStringUtil; import org.kie.kogito.Application; import org.kie.kogito.dmn.rest.DMNEvaluationErrorException; import org.kie.kogito.dmn.rest.DMNJSONUtils; @@ -73,10 +76,9 @@ public ResponseEntity dmn(@RequestBody(required = false) $inputType$ variable @GetMapping(produces = MediaType.APPLICATION_XML_VALUE) public String dmn() throws java.io.IOException { - return new String(org.drools.util.IoUtils. - readBytesFromInputStream(this.getClass() - .getResourceAsStream(org.kie.dmn.feel.codegen.feel11.CodegenStringUtil.escapeIdentifier("$modelName$") + - ".dmn_nologic"))); + try (InputStream is = this.getClass().getResourceAsStream(CodegenStringUtil.escapeIdentifier("$modelName$") + ".dmn_nologic")) { + return new String(org.drools.util.IoUtils.readBytesFromInputStream(Objects.requireNonNull(is))); + } } private Entry buildFailedEvaluationResponse(KogitoDMNResult result){ diff --git a/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PMMLRestResourceGeneratorTest.java b/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PMMLRestResourceGeneratorTest.java index 3295646907e..8fe6c0dd94b 100644 --- a/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PMMLRestResourceGeneratorTest.java +++ b/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PMMLRestResourceGeneratorTest.java @@ -22,6 +22,7 @@ import java.util.NoSuchElementException; import java.util.Optional; +import org.drools.codegen.common.di.impl.CDIDependencyInjectionAnnotator; import org.drools.util.StringUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -30,7 +31,6 @@ import org.kie.kogito.codegen.api.context.KogitoBuildContext; import org.kie.kogito.codegen.api.context.impl.QuarkusKogitoBuildContext; import org.kie.kogito.codegen.api.context.impl.SpringBootKogitoBuildContext; -import org.kie.kogito.codegen.api.di.impl.CDIDependencyInjectionAnnotator; import org.kie.kogito.codegen.api.template.TemplatedGenerator; import org.kie.pmml.commons.model.KiePMMLModel; diff --git a/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PredictionCodegenUtilsTest.java b/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PredictionCodegenUtilsTest.java index 93dda1c71b7..3442c2de184 100644 --- a/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PredictionCodegenUtilsTest.java +++ b/kogito-codegen-modules/kogito-codegen-predictions/src/test/java/org/kie/kogito/codegen/prediction/PredictionCodegenUtilsTest.java @@ -42,8 +42,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.drools.codegen.common.GeneratedFileType.COMPILED_CLASS; +import static org.drools.codegen.common.GeneratedFileType.REST; import static org.drools.codegen.common.GeneratedFileType.STATIC_HTTP_RESOURCE; -import static org.drools.model.codegen.execmodel.GeneratedFile.Type.REST; import static org.kie.kogito.pmml.CommonTestUtility.getKiePMMLModelInternal; import static org.kie.kogito.pmml.CommonTestUtility.getRandomMiningFields; import static org.kie.kogito.pmml.CommonTestUtility.getRandomOutputField; diff --git a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/rules/PublishEventBusinessRuleIT.java b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/rules/PublishEventBusinessRuleIT.java index dac4a03abe9..2a962e4a6d9 100644 --- a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/rules/PublishEventBusinessRuleIT.java +++ b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/rules/PublishEventBusinessRuleIT.java @@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.kie.kogito.Application; @@ -32,16 +33,19 @@ import org.kie.kogito.codegen.data.Person; import org.kie.kogito.event.DataEvent; import org.kie.kogito.event.EventPublisher; -import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceNodeDataEvent; +import org.kie.kogito.event.process.ProcessInstanceNodeEventBody; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateEventBody; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; +import org.kie.kogito.event.process.ProcessInstanceVariableEventBody; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.Processes; import org.kie.kogito.uow.UnitOfWork; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; public class PublishEventBusinessRuleIT extends AbstractRulesCodegenIT { @@ -73,23 +77,27 @@ public void testBusinessRuleProcessStartToEnd() throws Exception { assertThat(result.toMap().get("person")).isNotNull().hasFieldOrPropertyWithValue("adult", true); uow.end(); - ProcessInstanceDataEvent processDataEvent = publisher.extract().stream().filter(ProcessInstanceDataEvent.class::isInstance).map(ProcessInstanceDataEvent.class::cast).findFirst().orElseThrow(); - assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); + List> events = publisher.extract(); + ProcessInstanceStateDataEvent processDataEvent = + events.stream().filter(ProcessInstanceStateDataEvent.class::isInstance).map(ProcessInstanceStateDataEvent.class::cast).findFirst().orElseThrow(); assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNull(); assertThat(processDataEvent.getKogitoRootProcessInstanceId()).isNull(); assertThat(processDataEvent.getKogitoProcessId()).isEqualTo("BusinessRuleTask"); assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); assertThat(processDataEvent.getSource()).hasToString("http://myhost/BusinessRuleTask"); - ProcessInstanceEventBody body = assertProcessInstanceEvent(processDataEvent, "BusinessRuleTask", "Default Process", 2); + assertProcessInstanceEvent(processDataEvent, "BusinessRuleTask", "Default Process", 2); + + List> nodeEvents = events.stream().filter(ProcessInstanceNodeDataEvent.class::isInstance).collect(Collectors.toList()); - assertThat(body.getNodeInstances()).hasSize(3).extractingResultOf("getNodeType").contains("StartNode", "RuleSetNode", "EndNode"); + assertThat(nodeEvents).hasSize(6).map(e -> (ProcessInstanceNodeEventBody) e.getData()).extractingResultOf("getNodeType").containsOnly("StartNode", "RuleSetNode", "EndNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); + List variableEvents = + events.stream().filter(ProcessInstanceVariableDataEvent.class::isInstance).map(ProcessInstanceVariableDataEvent.class::cast).collect(Collectors.toList()); - assertThat(body.getVariables()).hasSize(1).containsKey("person"); - assertThat(body.getVariables().get("person")).isNotNull().hasFieldOrPropertyWithValue("adult", true); + assertThat(variableEvents) + .extracting(e -> e.getData().getVariableName(), e -> ((Person) e.getData().getVariableValue()).isAdult()) + .containsExactlyInAnyOrder(tuple("person", true), tuple("person", true)); } @Test @@ -153,11 +161,11 @@ public void testBusinessRuleProcessStartToEndWithVariableTracked() throws Except uow.end(); List> events = publisher.extract(); - assertThat(events).isNotNull().hasSize(2); + assertThat(events).isNotNull().hasSize(10); - DataEvent event = events.get(0); - assertThat(event).isInstanceOf(ProcessInstanceDataEvent.class); - ProcessInstanceDataEvent processDataEvent = (ProcessInstanceDataEvent) event; + DataEvent event = events.get(9); + assertThat(event).isInstanceOf(ProcessInstanceStateDataEvent.class); + ProcessInstanceStateDataEvent processDataEvent = (ProcessInstanceStateDataEvent) event; assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNull(); assertThat(processDataEvent.getKogitoRootProcessInstanceId()).isNull(); @@ -165,59 +173,44 @@ public void testBusinessRuleProcessStartToEndWithVariableTracked() throws Except assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); assertThat(processDataEvent.getSource()).hasToString("http://myhost/BusinessRuleTask"); - ProcessInstanceEventBody body = assertProcessInstanceEvent(events.get(0), "BusinessRuleTask", "Default Process", 2); + List> nodeEvents = events.stream().filter(ProcessInstanceNodeDataEvent.class::isInstance).map(e -> (ProcessInstanceNodeDataEvent) e).filter(e -> e.getData().getEventType() == 1) + .collect(Collectors.toList()); + assertThat(nodeEvents).hasSize(3).map(e -> (ProcessInstanceNodeEventBody) e.getData()).extractingResultOf("getNodeType").containsOnly("StartNode", "RuleSetNode", "EndNode"); - assertThat(body.getNodeInstances()).hasSize(3).extractingResultOf("getNodeType").contains("StartNode", "RuleSetNode", "EndNode"); + assertProcessInstanceEvent(event, "BusinessRuleTask", "Default Process", 2); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); + List> varaibleEvents = events.stream().filter(ProcessInstanceVariableDataEvent.class::isInstance).map(e -> (ProcessInstanceVariableDataEvent) e).collect(Collectors.toList()); + event = varaibleEvents.get(0); + assertThat(event).isInstanceOf(ProcessInstanceVariableDataEvent.class); - assertThat(body.getVariables()).hasSize(1).containsKey("person"); - assertThat(body.getVariables().get("person")).isNotNull().hasFieldOrPropertyWithValue("adult", true); - - event = events.get(1); - assertThat(event).isInstanceOf(VariableInstanceDataEvent.class); - - VariableInstanceDataEvent variableDataEvent = (VariableInstanceDataEvent) event; + ProcessInstanceVariableDataEvent variableDataEvent = (ProcessInstanceVariableDataEvent) event; assertThat(variableDataEvent.getKogitoProcessInstanceId()).isNotNull(); assertThat(variableDataEvent.getKogitoRootProcessId()).isNull(); assertThat(variableDataEvent.getKogitoRootProcessInstanceId()).isNull(); assertThat(variableDataEvent.getKogitoProcessId()).isEqualTo("BusinessRuleTask"); // first is event created based on process start so no node associated - VariableInstanceEventBody variableEventBody = variableDataEvent.getData(); + ProcessInstanceVariableEventBody variableEventBody = variableDataEvent.getData(); assertThat(variableEventBody).isNotNull(); - assertThat(variableEventBody.getChangeDate()).isNotNull(); + assertThat(variableEventBody.getEventDate()).isNotNull(); assertThat(variableEventBody.getProcessInstanceId()).isEqualTo(variableDataEvent.getKogitoProcessInstanceId()); assertThat(variableEventBody.getProcessId()).isEqualTo("BusinessRuleTask"); - assertThat(variableEventBody.getRootProcessId()).isNull(); - assertThat(variableEventBody.getRootProcessInstanceId()).isNull(); assertThat(variableEventBody.getVariableName()).isEqualTo("person"); assertThat(variableEventBody.getVariableValue()).isNotNull(); - assertThat(variableEventBody.getVariablePreviousValue()).isNotNull().hasFieldOrPropertyWithValue("adult", true); - assertThat(variableEventBody.getChangedByNodeId()).isEqualTo("BusinessRuleTask_2"); - assertThat(variableEventBody.getChangedByNodeName()).isEqualTo("Business Rule Task"); - assertThat(variableEventBody.getChangedByNodeType()).isEqualTo("RuleSetNode"); - assertThat(variableEventBody.getIdentity()).isNull(); } /* * Helper methods */ - protected ProcessInstanceEventBody assertProcessInstanceEvent(DataEvent event, String processId, String processName, Integer state) { + protected ProcessInstanceStateEventBody assertProcessInstanceEvent(DataEvent event, String processId, String processName, Integer state) { - assertThat(event).isInstanceOf(ProcessInstanceDataEvent.class); - ProcessInstanceEventBody body = ((ProcessInstanceDataEvent) event).getData(); + assertThat(event).isInstanceOf(ProcessInstanceStateDataEvent.class); + ProcessInstanceStateEventBody body = ((ProcessInstanceStateDataEvent) event).getData(); assertThat(body).isNotNull(); - assertThat(body.getId()).isNotNull(); - assertThat(body.getStartDate()).isNotNull(); - if (state == ProcessInstance.STATE_ACTIVE || state == ProcessInstance.STATE_ERROR) { - assertThat(body.getEndDate()).isNull(); - } else { - assertThat(body.getEndDate()).isNotNull(); - } + assertThat(body.getProcessInstanceId()).isNotNull(); + assertThat(body.getEventDate()).isNotNull(); assertThat(body.getParentInstanceId()).isNull(); - assertThat(body.getRootInstanceId()).isNull(); + assertThat(body.getRootProcessInstanceId()).isNull(); assertThat(body.getProcessId()).isEqualTo(processId); assertThat(body.getProcessName()).isEqualTo(processName); assertThat(body.getState()).isEqualTo(state); @@ -225,7 +218,7 @@ protected ProcessInstanceEventBody assertProcessInstanceEvent(DataEvent event assertThat(event.getSource()).hasToString("http://myhost/" + processId); assertThat(event.getTime()).isBeforeOrEqualTo(ZonedDateTime.now().toOffsetDateTime()); - assertThat(((ProcessInstanceDataEvent) event).getKogitoAddons()).isEqualTo("test"); + assertThat(((ProcessInstanceStateDataEvent) event).getKogitoAddons()).isEqualTo("test"); return body; } diff --git a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java index 0291cf008fd..6994a398018 100644 --- a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java +++ b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; @@ -37,17 +36,19 @@ import org.kie.kogito.codegen.AbstractCodegenIT; import org.kie.kogito.event.DataEvent; import org.kie.kogito.event.EventPublisher; -import org.kie.kogito.event.process.MilestoneEventBody; -import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceErrorDataEvent; +import org.kie.kogito.event.process.ProcessInstanceNodeDataEvent; +import org.kie.kogito.event.process.ProcessInstanceNodeEventBody; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateEventBody; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceStateEventBody; import org.kie.kogito.process.Process; import org.kie.kogito.process.ProcessError; import org.kie.kogito.process.ProcessInstance; import org.kie.kogito.process.Processes; import org.kie.kogito.process.WorkItem; -import org.kie.kogito.process.flexible.ItemDescription.Status; import org.kie.kogito.uow.UnitOfWork; import static org.assertj.core.api.Assertions.assertThat; @@ -77,11 +78,10 @@ public void testProcessWithMilestoneEvents() throws Exception { uow.end(); List> events = publisher.extract(); - assertThat(events).hasSize(1); - DataEvent event = events.get(0); - assertThat(event).isInstanceOf(ProcessInstanceDataEvent.class); - ProcessInstanceDataEvent processDataEvent = (ProcessInstanceDataEvent) event; + DataEvent event = findProcessInstanceEvent(events, ProcessInstance.STATE_COMPLETED).get(); + assertThat(event).isInstanceOf(ProcessInstanceStateDataEvent.class); + ProcessInstanceStateDataEvent processDataEvent = (ProcessInstanceStateDataEvent) event; assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); assertThat(processDataEvent.getKogitoProcessInstanceVersion()).isEqualTo("1.0"); assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNull(); @@ -90,12 +90,13 @@ public void testProcessWithMilestoneEvents() throws Exception { assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); assertThat(processDataEvent.getSource()).hasToString("http://myhost/SimpleMilestone"); - Set milestones = ((ProcessInstanceDataEvent) event).getData().getMilestones(); - assertThat(milestones) - .hasSize(2) - .extracting(e -> e.getName(), e -> e.getStatus()) - .containsExactlyInAnyOrder(tuple("AutoStartMilestone", Status.COMPLETED.name()), - tuple("SimpleMilestone", Status.COMPLETED.name())); + List milestoneEvents = events.stream().filter(ProcessInstanceNodeDataEvent.class::isInstance).map(ProcessInstanceNodeDataEvent.class::cast) + .filter(e -> e.getData().getNodeType().equals("MilestoneNode") && e.getData().getEventType() == ProcessInstanceNodeEventBody.EVENT_TYPE_EXIT).collect(Collectors.toList()); + + assertThat(milestoneEvents) + .extracting(e -> e.getData().getNodeName(), e -> e.getData().getEventType()) + .containsExactlyInAnyOrder(tuple("AutoStartMilestone", ProcessInstanceNodeEventBody.EVENT_TYPE_EXIT), tuple("SimpleMilestone", ProcessInstanceNodeEventBody.EVENT_TYPE_EXIT)); + } @Test @@ -123,9 +124,9 @@ public void testCompensationProcess() throws Exception { List> events = publisher.extract(); - Optional> event = events.stream().filter(ProcessInstanceDataEvent.class::isInstance).findFirst(); + Optional> event = findProcessInstanceEvent(events, ProcessInstance.STATE_COMPLETED); assertThat(event).as("There is no process instance event being published").isPresent(); - ProcessInstanceDataEvent processDataEvent = (ProcessInstanceDataEvent) event.orElseThrow(); + ProcessInstanceStateDataEvent processDataEvent = (ProcessInstanceStateDataEvent) event.orElseThrow(); assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); assertThat(processDataEvent.getKogitoProcessInstanceVersion()).isEqualTo("1.0"); assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNull(); @@ -134,17 +135,24 @@ public void testCompensationProcess() throws Exception { assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); assertThat(processDataEvent.getSource()).hasToString("http://myhost/compensateAll"); - ProcessInstanceEventBody body = assertProcessInstanceEvent(events.get(0), "compensateAll", "Compensate All", 2); + assertProcessInstanceEvent(event.get(), "compensateAll", "Compensate All", ProcessInstanceStateEventBody.EVENT_TYPE_ENDED); + + List nodes = findNodeInstanceEvents(events, 2); + assertThat(nodes).hasSize(9).extractingResultOf("getNodeType").contains("StartNode", "ActionNode", "BoundaryEventNode", "EndNode"); + + } - assertThat(body.getNodeInstances()).hasSize(9).extractingResultOf("getNodeType").contains("StartNode", "ActionNode", "BoundaryEventNode", "EndNode"); + private Optional findUserTaskInstanceEvent(List> events, String status) { + return events.stream().filter(UserTaskInstanceStateDataEvent.class::isInstance).map(e -> (UserTaskInstanceStateDataEvent) e).filter(e -> status.equals(e.getData().getState())).findAny(); + } - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); + private Optional> findProcessInstanceEvent(List> events, int state) { + return events.stream().filter(ProcessInstanceStateDataEvent.class::isInstance).filter(e -> ((ProcessInstanceStateEventBody) e.getData()).getState() == state).findAny(); + } - assertThat(body.getVariables()) - .hasSize(2) - .containsEntry("counter", 2) - .containsEntry("counter2", 2); + private List findNodeInstanceEvents(List> events, int eventType) { + return events.stream().filter(ProcessInstanceNodeDataEvent.class::isInstance).map(e -> (ProcessInstanceNodeEventBody) e.getData()).filter(e -> e.getEventType() == eventType) + .collect(Collectors.toList()); } @Test @@ -170,13 +178,19 @@ public void testBasicUserTaskProcess() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE); List> events = publisher.extract(); - assertThat(events).hasSize(2); - ProcessInstanceEventBody body = assertProcessInstanceEvent(events.get(0), "UserTasksProcess", "UserTasksProcess", 1); - assertThat(body.getNodeInstances()).hasSize(2).extractingResultOf("getNodeType").contains("StartNode", "HumanTaskNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").containsNull();// human task is active thus null for leave time - assertUserTaskInstanceEvent(events.get(1), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task"); + Optional> processEvent = findProcessInstanceEvent(events, ProcessInstance.STATE_ACTIVE); + assertProcessInstanceEvent(processEvent.get(), "UserTasksProcess", "UserTasksProcess", 1); + + List triggered = findNodeInstanceEvents(events, 1); + assertThat(triggered).hasSize(2).extractingResultOf("getNodeType").containsOnly("StartNode", "HumanTaskNode"); + + List left = findNodeInstanceEvents(events, 2); + assertThat(left).hasSize(1).extractingResultOf("getNodeType").containsOnly("StartNode"); + + Optional userFirstTask = findUserTaskInstanceEvent(events, "Ready"); + assertThat(userFirstTask).isPresent(); + assertUserTaskInstanceEvent(userFirstTask.get(), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task"); List workItems = processInstance.workItems(SecurityPolicy.of(IdentityProviders.of("john"))); assertThat(workItems).hasSize(1); @@ -188,14 +202,18 @@ public void testBasicUserTaskProcess() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE); events = publisher.extract(); - assertThat(events).hasSize(3); - body = assertProcessInstanceEvent(events.get(0), "UserTasksProcess", "UserTasksProcess", 1); - assertThat(body.getNodeInstances()).hasSize(2).extractingResultOf("getNodeType").contains("HumanTaskNode", "HumanTaskNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").containsNull();// human task is active thus null for leave time - assertUserTaskInstanceEvent(events.get(1), "SecondTask", null, "1", "Ready", "UserTasksProcess", "Second Task"); - assertUserTaskInstanceEvent(events.get(2), "FirstTask", null, "1", "Completed", "UserTasksProcess", "First Task"); + triggered = findNodeInstanceEvents(events, 1); + assertThat(triggered).hasSize(1).extractingResultOf("getNodeType").containsOnly("HumanTaskNode"); + + left = findNodeInstanceEvents(events, 1); + assertThat(left).hasSize(1).extractingResultOf("getNodeType").containsOnly("HumanTaskNode"); + + Optional firstUserTaskInstance = findUserTaskInstanceEvent(events, "Ready"); + Optional secondUserTaskInstance = findUserTaskInstanceEvent(events, "Completed"); + + assertUserTaskInstanceEvent(firstUserTaskInstance.get(), "SecondTask", null, "1", "Ready", "UserTasksProcess", "Second Task"); + assertUserTaskInstanceEvent(secondUserTaskInstance.get(), "FirstTask", null, "1", "Completed", "UserTasksProcess", "First Task"); workItems = processInstance.workItems(SecurityPolicy.of(IdentityProviders.of("john"))); assertThat(workItems).hasSize(1); @@ -207,11 +225,15 @@ public void testBasicUserTaskProcess() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED); events = publisher.extract(); - assertThat(events).hasSize(2); - body = assertProcessInstanceEvent(events.get(0), "UserTasksProcess", "UserTasksProcess", 2); - assertThat(body.getNodeInstances()).hasSize(2).extractingResultOf("getNodeType").contains("HumanTaskNode", "EndNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); + List userTaskEvents = + events.stream().filter(ProcessInstanceStateDataEvent.class::isInstance).map(ProcessInstanceStateDataEvent.class::cast).collect(Collectors.toList()); + assertProcessInstanceEvent(userTaskEvents.get(0), "UserTasksProcess", "UserTasksProcess", 2); + + triggered = findNodeInstanceEvents(events, 1); + assertThat(triggered).hasSize(1).extractingResultOf("getNodeType").containsOnly("EndNode"); + + left = findNodeInstanceEvents(events, 2); + assertThat(left).hasSize(2).extractingResultOf("getNodeType").containsOnly("HumanTaskNode", "EndNode"); assertUserTaskInstanceEvent(events.get(1), "SecondTask", null, "1", "Completed", "UserTasksProcess", "Second Task"); } @@ -239,13 +261,16 @@ public void testBasicUserTaskProcessAbort() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE); List> events = publisher.extract(); - assertThat(events).hasSize(2); - ProcessInstanceEventBody body = assertProcessInstanceEvent(events.get(0), "UserTasksProcess", "UserTasksProcess", 1); - assertThat(body.getNodeInstances()).hasSize(2).extractingResultOf("getNodeType").contains("StartNode", "HumanTaskNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").containsNull();// human task is active thus null for leave time - assertUserTaskInstanceEvent(events.get(1), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task"); + Optional> active = findProcessInstanceEvent(events, ProcessInstance.STATE_ACTIVE); + assertProcessInstanceEvent(active.get(), "UserTasksProcess", "UserTasksProcess", ProcessInstance.STATE_ACTIVE); + + List triggered = findNodeInstanceEvents(events, 1); + assertThat(triggered).hasSize(2).extractingResultOf("getNodeName").containsOnly("StartProcess", "First Task"); + + Optional event = findUserTaskInstanceEvent(events, "Ready"); + assertThat(event).isPresent(); + assertUserTaskInstanceEvent(event.get(), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task"); List workItems = processInstance.workItems(SecurityPolicy.of(IdentityProviders.of("john"))); assertThat(workItems).hasSize(1); @@ -257,12 +282,13 @@ public void testBasicUserTaskProcessAbort() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ABORTED); events = publisher.extract(); - assertThat(events).hasSize(2); - body = assertProcessInstanceEvent(events.get(0), "UserTasksProcess", "UserTasksProcess", ProcessInstance.STATE_ABORTED); - assertThat(body.getNodeInstances()).hasSize(1).extractingResultOf("getNodeType").contains("HumanTaskNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); - assertUserTaskInstanceEvent(events.get(1), "FirstTask", null, "1", "Aborted", "UserTasksProcess", "First Task"); + assertThat(events).hasSize(4); + + triggered = findNodeInstanceEvents(events, 2); + assertThat(triggered).hasSize(1).extractingResultOf("getNodeName").containsOnly("First Task"); + + assertProcessInstanceEvent(events.get(3), "UserTasksProcess", "UserTasksProcess", ProcessInstance.STATE_ABORTED); + } @Test @@ -289,14 +315,20 @@ public void testBasicUserTaskProcessWithSecurityRoles() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE); List> events = publisher.extract(); - assertThat(events).hasSize(2); - ProcessInstanceEventBody body = assertProcessInstanceEvent(events.get(0), "UserTasksProcess", "UserTasksProcess", 1); + + Optional> completed = findProcessInstanceEvent(events, ProcessInstanceStateEventBody.EVENT_TYPE_STARTED); + ProcessInstanceStateEventBody body = assertProcessInstanceEvent(completed.get(), "UserTasksProcess", "UserTasksProcess", 1); assertThat(body.getRoles()).hasSize(2).contains("employees", "managers"); - assertThat(body.getNodeInstances()).hasSize(2).extractingResultOf("getNodeType").contains("StartNode", "HumanTaskNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").containsNull();// human task is active thus null for leave time - assertUserTaskInstanceEvent(events.get(1), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task"); + List triggered = findNodeInstanceEvents(events, 1); + assertThat(triggered).hasSize(2).extractingResultOf("getNodeType").containsOnly("StartNode", "HumanTaskNode"); + + List left = findNodeInstanceEvents(events, 2); + assertThat(left).hasSize(1).extractingResultOf("getNodeType").containsOnly("StartNode"); + + Optional userTask = findUserTaskInstanceEvent(events, "Ready"); + assertThat(userTask).isPresent(); + assertUserTaskInstanceEvent(userTask.get(), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task"); } @Test @@ -331,43 +363,21 @@ public void testBasicCallActivityTask() throws Exception { .isNotNull().containsEntry("y", "new value") .isNotNull().containsEntry("x", "a"); - List> events = publisher.extract().stream().filter(ProcessInstanceDataEvent.class::isInstance).collect(Collectors.toList()); - assertThat(events).hasSize(2); - - DataEvent parent = null; - DataEvent child = null; - - for (DataEvent e : events) { - ProcessInstanceDataEvent processDataEvent = (ProcessInstanceDataEvent) e; - if (processDataEvent.getKogitoProcessId().equals("ParentProcess")) { - parent = e; - assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); - assertThat(processDataEvent.getKogitoProcessInstanceVersion()).isEqualTo("1.0"); - assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNull(); - assertThat(processDataEvent.getKogitoRootProcessInstanceId()).isNull(); - assertThat(processDataEvent.getKogitoRootProcessId()).isNull(); - assertThat(processDataEvent.getKogitoProcessId()).isEqualTo("ParentProcess"); - assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); - } else { - child = e; - assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); - assertThat(processDataEvent.getKogitoProcessInstanceVersion()).isEqualTo("1"); - assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNotNull(); - assertThat(processDataEvent.getKogitoRootProcessInstanceId()).isNotNull(); - assertThat(processDataEvent.getKogitoProcessId()).isEqualTo("SubProcess"); - assertThat(processDataEvent.getKogitoRootProcessId()).isEqualTo("ParentProcess"); - assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); - } - } - ProcessInstanceEventBody parentBody = assertProcessInstanceEvent(parent, "ParentProcess", "Parent Process", 2); - assertThat(parentBody.getNodeInstances()).hasSize(3).extractingResultOf("getNodeType").contains("StartNode", "SubProcessNode", "EndNode"); - assertThat(parentBody.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(parentBody.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); - - ProcessInstanceEventBody childBody = assertProcessInstanceEventWithParentId(child, "SubProcess", "Sub Process", 2); - assertThat(childBody.getNodeInstances()).hasSize(3).extractingResultOf("getNodeType").contains("StartNode", "ActionNode", "EndNode"); - assertThat(childBody.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(childBody.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); + List> events = publisher.extract(); + + List> parentEvents = events.stream().filter(e -> e.getKogitoProcessId().equals("ParentProcess")).collect(Collectors.toList()); + List> childEvents = events.stream().filter(e -> e.getKogitoProcessId().equals("SubProcess")).collect(Collectors.toList()); + + DataEvent parentBody = findProcessInstanceEvent(parentEvents, ProcessInstanceStateEventBody.EVENT_TYPE_ENDED).get(); + DataEvent childBody = findProcessInstanceEvent(childEvents, ProcessInstanceStateEventBody.EVENT_TYPE_ENDED).get(); + + assertProcessInstanceEvent(parentBody, "ParentProcess", "Parent Process", ProcessInstanceStateEventBody.EVENT_TYPE_ENDED); + assertThat(findNodeInstanceEvents(parentEvents, ProcessInstanceStateEventBody.EVENT_TYPE_ENDED)).hasSize(3).extractingResultOf("getNodeType").containsOnly("StartNode", "SubProcessNode", + "EndNode"); + + assertProcessInstanceEventWithParentId(childBody, "SubProcess", "Sub Process", ProcessInstanceStateEventBody.EVENT_TYPE_ENDED); + assertThat(findNodeInstanceEvents(childEvents, ProcessInstanceStateEventBody.EVENT_TYPE_ENDED)).hasSize(3).extractingResultOf("getNodeType").containsOnly("StartNode", "ActionNode", "EndNode"); + } @Test @@ -398,7 +408,10 @@ public void testExclusiveGatewayStartToEnd() throws Exception { assertThat(result.toMap()).hasSize(2).containsKeys("x", "y"); uow.end(); - ProcessInstanceDataEvent processDataEvent = publisher.extract().stream().filter(ProcessInstanceDataEvent.class::isInstance).map(ProcessInstanceDataEvent.class::cast).findFirst().orElseThrow(); + List> events = publisher.extract(); + + ProcessInstanceStateDataEvent processDataEvent = + events.stream().filter(ProcessInstanceStateDataEvent.class::isInstance).map(ProcessInstanceStateDataEvent.class::cast).findFirst().orElseThrow(); assertThat(processDataEvent.getKogitoProcessInstanceId()).isNotNull(); assertThat(processDataEvent.getKogitoProcessInstanceVersion()).isEqualTo("1.0"); assertThat(processDataEvent.getKogitoParentProcessInstanceId()).isNull(); @@ -406,12 +419,11 @@ public void testExclusiveGatewayStartToEnd() throws Exception { assertThat(processDataEvent.getKogitoProcessId()).isEqualTo("ExclusiveSplit"); assertThat(processDataEvent.getKogitoProcessInstanceState()).isEqualTo("2"); - ProcessInstanceEventBody body = assertProcessInstanceEvent(processDataEvent, "ExclusiveSplit", "Test", 2); + assertProcessInstanceEvent(processDataEvent, "ExclusiveSplit", "Test", 2); - assertThat(body.getNodeInstances()).hasSize(6).extractingResultOf("getNodeType").contains("StartNode", "ActionNode", "Split", "Join", "EndNode", "WorkItemNode"); + List nodes = findNodeInstanceEvents(events, 2); + assertThat(nodes).hasSize(6).extractingResultOf("getNodeType").contains("StartNode", "ActionNode", "Split", "Join", "EndNode", "WorkItemNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").allMatch(v -> v != null); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -439,17 +451,17 @@ public void testServiceTaskProcessWithError() throws Exception { uow.end(); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ERROR); - List> events = publisher.extract().stream().filter(ProcessInstanceDataEvent.class::isInstance).collect(Collectors.toList()); + List> rawEvents = publisher.extract(); + List> events = rawEvents.stream().filter(ProcessInstanceStateDataEvent.class::isInstance).collect(Collectors.toList()); assertThat(events).hasSize(1); - ProcessInstanceEventBody body = assertProcessInstanceEvent(events.get(0), "ServiceProcessDifferentOperations", "Service Process", 5); - assertThat(body.getNodeInstances()).hasSize(2).extractingResultOf("getNodeType").contains("StartNode", "WorkItemNode"); - assertThat(body.getNodeInstances()).extractingResultOf("getTriggerTime").allMatch(v -> v != null); - assertThat(body.getNodeInstances()).extractingResultOf("getLeaveTime").containsNull();// human task is active thus null for leave time + assertProcessInstanceEvent(events.get(0), "ServiceProcessDifferentOperations", "Service Process", 5); - assertThat(body.getError()).isNotNull(); - assertThat(body.getError().getErrorMessage()).contains("java.lang.NullPointerException"); - assertThat(body.getError().getNodeDefinitionId()).isEqualTo("_38E04E27-3CCA-47F9-927B-E37DC4B8CE25"); + List errorEvents = + rawEvents.stream().filter(ProcessInstanceErrorDataEvent.class::isInstance).map(ProcessInstanceErrorDataEvent.class::cast).collect(Collectors.toList()); + assertThat(errorEvents).hasSize(1); + assertThat(errorEvents.get(0).getData().getErrorMessage()).contains("java.lang.NullPointerException"); + assertThat(errorEvents.get(0).getData().getNodeDefinitionId()).isEqualTo("_38E04E27-3CCA-47F9-927B-E37DC4B8CE25"); parameters.put("s", "john"); m.fromMap(parameters); @@ -458,12 +470,9 @@ public void testServiceTaskProcessWithError() throws Exception { processInstance.updateVariables(m); uow.end(); - events = publisher.extract().stream().filter(ProcessInstanceDataEvent.class::isInstance).collect(Collectors.toList()); + events = publisher.extract(); assertThat(events).hasSize(1); - body = assertProcessInstanceEvent(events.get(0), "ServiceProcessDifferentOperations", "Service Process", 5); - assertThat(body.getError()).isNotNull(); - assertThat(body.getError().getErrorMessage()).contains("java.lang.NullPointerException"); - assertThat(body.getError().getNodeDefinitionId()).isEqualTo("_38E04E27-3CCA-47F9-927B-E37DC4B8CE25"); + assertThat(events.get(0)).isInstanceOf(ProcessInstanceVariableDataEvent.class); uow = app.unitOfWorkManager().newUnitOfWork(); uow.start(); @@ -472,11 +481,10 @@ public void testServiceTaskProcessWithError() throws Exception { } uow.end(); - events = publisher.extract().stream().filter(ProcessInstanceDataEvent.class::isInstance).collect(Collectors.toList()); + events = publisher.extract().stream().filter(ProcessInstanceStateDataEvent.class::isInstance).collect(Collectors.toList()); assertThat(events).hasSize(1); - body = assertProcessInstanceEvent(events.get(0), "ServiceProcessDifferentOperations", "Service Process", 2); - assertThat(body.getError()).isNull(); + assertProcessInstanceEvent(events.get(0), "ServiceProcessDifferentOperations", "Service Process", 2); assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED); Model result = (Model) processInstance.variables(); @@ -488,21 +496,29 @@ public void testServiceTaskProcessWithError() throws Exception { * Helper methods */ - protected ProcessInstanceEventBody assertProcessInstanceEvent(DataEvent event, String processId, String processName, Integer state) { + protected ProcessInstanceNodeEventBody assertNodeInstanceEvent(DataEvent event, String processInstanceId, String nodeName, Integer eventType) { - assertThat(event).isInstanceOf(ProcessInstanceDataEvent.class); - ProcessInstanceEventBody body = ((ProcessInstanceDataEvent) event).getData(); + assertThat(event).isInstanceOf(ProcessInstanceNodeDataEvent.class); + ProcessInstanceNodeEventBody body = ((ProcessInstanceNodeDataEvent) event).getData(); assertThat(body).isNotNull(); - assertThat(body.getId()).isNotNull(); - assertThat(body.getVersion()).isNotNull(); - assertThat(body.getStartDate()).isNotNull(); - if (state == ProcessInstance.STATE_ACTIVE || state == ProcessInstance.STATE_ERROR) { - assertThat(body.getEndDate()).isNull(); - } else { - assertThat(body.getEndDate()).isNotNull(); - } + assertThat(body.getProcessInstanceId()).isNotNull(); + assertThat(body.getProcessInstanceId()).isEqualTo(processInstanceId); + assertThat(body.getEventType()).isEqualTo(eventType); + assertThat(body.getNodeName()).isEqualTo(nodeName); + + return body; + } + + protected ProcessInstanceStateEventBody assertProcessInstanceEvent(DataEvent event, String processId, String processName, Integer state) { + + assertThat(event).isInstanceOf(ProcessInstanceStateDataEvent.class); + ProcessInstanceStateEventBody body = ((ProcessInstanceStateDataEvent) event).getData(); + assertThat(body).isNotNull(); + assertThat(body.getProcessInstanceId()).isNotNull(); + assertThat(body.getProcessVersion()).isNotNull(); + assertThat(body.getEventDate()).isNotNull(); assertThat(body.getParentInstanceId()).isNull(); - assertThat(body.getRootInstanceId()).isNull(); + assertThat(body.getRootProcessInstanceId()).isNull(); assertThat(body.getProcessId()).isEqualTo(processId); assertThat(body.getProcessName()).isEqualTo(processName); assertThat(body.getState()).isEqualTo(state); @@ -510,55 +526,44 @@ protected ProcessInstanceEventBody assertProcessInstanceEvent(DataEvent event assertThat(event.getSource()).hasToString("http://myhost/" + processId); assertThat(event.getTime()).isBeforeOrEqualTo(ZonedDateTime.now().toOffsetDateTime()); - assertThat(((ProcessInstanceDataEvent) event).getKogitoAddons()).isEqualTo("test"); + assertThat(((ProcessInstanceStateDataEvent) event).getKogitoAddons()).isEqualTo("test"); return body; } - protected UserTaskInstanceEventBody assertUserTaskInstanceEvent(DataEvent event, String taskName, String taskDescription, String taskPriority, String taskState, String processId, + protected UserTaskInstanceStateEventBody assertUserTaskInstanceEvent(DataEvent event, String taskName, String taskDescription, String taskPriority, String taskState, String processId, String nodeName) { - assertThat(event).isInstanceOf(UserTaskInstanceDataEvent.class); - UserTaskInstanceEventBody body = ((UserTaskInstanceDataEvent) event).getData(); + assertThat(event).isInstanceOf(UserTaskInstanceStateDataEvent.class); + UserTaskInstanceStateEventBody body = ((UserTaskInstanceStateDataEvent) event).getData(); assertThat(body).isNotNull(); - assertThat(body.getId()).isNotNull(); - assertThat(body.getTaskName()).isEqualTo(taskName); - assertThat(body.getTaskDescription()).isEqualTo(taskDescription); - assertThat(body.getReferenceName()).isEqualTo(nodeName); - assertThat(body.getTaskPriority()).isEqualTo(taskPriority); - assertThat(body.getStartDate()).isNotNull(); + assertThat(body.getUserTaskInstanceId()).isNotNull(); + assertThat(body.getUserTaskName()).isEqualTo(taskName); + assertThat(body.getUserTaskDescription()).isEqualTo(taskDescription); + assertThat(body.getUserTaskReferenceName()).isEqualTo(nodeName); + assertThat(body.getUserTaskPriority()).isEqualTo(taskPriority); + assertThat(body.getEventDate()).isNotNull(); assertThat(body.getState()).isEqualTo(taskState); - if (taskState.equals("Completed") || taskState.equals("Aborted")) { - assertThat(body.getCompleteDate()).isNotNull(); - } else { - assertThat(body.getCompleteDate()).isNull(); - } - assertThat(event.getSource()).hasToString("http://myhost/" + processId); assertThat(event.getTime()).isBeforeOrEqualTo(ZonedDateTime.now().toOffsetDateTime()); - assertThat(((UserTaskInstanceDataEvent) event).getKogitoAddons()).isEqualTo("test"); + assertThat(((UserTaskInstanceStateDataEvent) event).getKogitoAddons()).isEqualTo("test"); return body; } - protected ProcessInstanceEventBody assertProcessInstanceEventWithParentId(DataEvent event, String processId, String processName, Integer state) { + protected ProcessInstanceStateEventBody assertProcessInstanceEventWithParentId(DataEvent event, String processId, String processName, Integer state) { - assertThat(event).isInstanceOf(ProcessInstanceDataEvent.class); - ProcessInstanceEventBody body = ((ProcessInstanceDataEvent) event).getData(); + assertThat(event).isInstanceOf(ProcessInstanceStateDataEvent.class); + ProcessInstanceStateEventBody body = ((ProcessInstanceStateDataEvent) event).getData(); assertThat(body).isNotNull(); - assertThat(body.getId()).isNotNull(); - assertThat(body.getVersion()).isNotNull(); - assertThat(body.getStartDate()).isNotNull(); - if (state == ProcessInstance.STATE_ACTIVE) { - assertThat(body.getEndDate()).isNull(); - } else { - assertThat(body.getEndDate()).isNotNull(); - } + assertThat(body.getProcessInstanceId()).isNotNull(); + assertThat(body.getProcessVersion()).isNotNull(); + assertThat(body.getEventDate()).isNotNull(); assertThat(body.getParentInstanceId()).isNotNull(); - assertThat(body.getRootInstanceId()).isNotNull(); + assertThat(body.getRootProcessInstanceId()).isNotNull(); assertThat(body.getProcessId()).isEqualTo(processId); assertThat(body.getProcessName()).isEqualTo(processName); - assertThat(body.getState()).isEqualTo(state); + assertThat(body.getEventType()).isEqualTo(state); return body; } diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java index eece2d904ad..dfbb92dfb5d 100644 --- a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java +++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java @@ -43,6 +43,7 @@ import org.kie.kogito.codegen.core.CodegenUtils; import org.kie.kogito.codegen.core.GeneratorConfig; import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess; +import org.kie.kogito.internal.utils.ConversionUtils; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Modifier.Keyword; @@ -108,7 +109,7 @@ public ProcessResourceGenerator( this.context = context; this.process = process; this.processId = process.getId(); - this.processName = processId.substring(processId.lastIndexOf('.') + 1); + this.processName = ConversionUtils.sanitizeToSimpleName(processId); this.resourceClazzName = sanitizeClassName(processName + "Resource"); this.relativePath = process.getPackageName().replace(".", "/") + "/" + resourceClazzName + ".java"; this.modelfqcn = modelfqcn; diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/MessageProducerJavaTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/MessageProducerJavaTemplate.java index 0a1a6f48ab4..4eb7b7f1106 100644 --- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/MessageProducerJavaTemplate.java +++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/MessageProducerJavaTemplate.java @@ -23,7 +23,7 @@ import org.kie.kogito.event.EventMarshaller; import org.kie.kogito.event.impl.StringEventMarshaller; -import org.kie.kogito.event.process.ProcessDataEvent; +import org.kie.kogito.event.process.ProcessInstanceDataEvent; import org.kie.kogito.internal.process.runtime.KogitoProcessInstance; import com.fasterxml.jackson.databind.ObjectMapper; @@ -44,7 +44,7 @@ public void produce(KogitoProcessInstance pi, $Type$ eventData) { } private String marshall(KogitoProcessInstance pi, $Type$ eventData) throws IOException { - return marshaller.marshall(useCloudEvents.orElse(true) ? new ProcessDataEvent<>( + return marshaller.marshall(useCloudEvents.orElse(true) ? new ProcessInstanceDataEvent<>( "", "", eventData, diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryEndpointGenerator.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryEndpointGenerator.java index c0c6e9386d8..ef34f2e81d3 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryEndpointGenerator.java +++ b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryEndpointGenerator.java @@ -47,10 +47,10 @@ import com.github.javaparser.ast.type.Type; import static com.github.javaparser.StaticJavaParser.parseStatement; +import static org.drools.model.codegen.execmodel.util.RuleCodegenUtils.setGeneric; +import static org.drools.model.codegen.execmodel.util.RuleCodegenUtils.toKebabCase; +import static org.drools.model.codegen.execmodel.util.RuleCodegenUtils.toNonPrimitiveType; import static org.kie.kogito.codegen.api.Generator.REST_TYPE; -import static org.kie.kogito.codegen.rules.RuleCodegenUtils.setGeneric; -import static org.kie.kogito.codegen.rules.RuleCodegenUtils.toKebabCase; -import static org.kie.kogito.codegen.rules.RuleCodegenUtils.toNonPrimitiveType; public class QueryEndpointGenerator extends AbstractQueryEntrypointGenerator { diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryGenerator.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryGenerator.java index d2f4c4c2378..d0e98d00c14 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryGenerator.java +++ b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/QueryGenerator.java @@ -50,10 +50,10 @@ import com.github.javaparser.ast.stmt.Statement; import static org.drools.model.codegen.execmodel.generator.DrlxParseUtil.classToReferenceType; +import static org.drools.model.codegen.execmodel.util.RuleCodegenUtils.setGeneric; +import static org.drools.model.codegen.execmodel.util.RuleCodegenUtils.toCamelCase; import static org.drools.util.StringUtils.ucFirst; import static org.kie.kogito.codegen.rules.RuleCodegen.TEMPLATE_RULE_FOLDER; -import static org.kie.kogito.codegen.rules.RuleCodegenUtils.setGeneric; -import static org.kie.kogito.codegen.rules.RuleCodegenUtils.toCamelCase; public class QueryGenerator implements RuleFileGenerator { diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegen.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegen.java index 642acfbc1d7..c042be4002a 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegen.java +++ b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegen.java @@ -29,6 +29,7 @@ import org.drools.codegen.common.GeneratedFile; import org.drools.codegen.common.GeneratedFileType; import org.drools.drl.extensions.DecisionTableFactory; +import org.drools.drl.parser.DroolsError; import org.drools.model.codegen.execmodel.PackageModelWriter; import org.drools.model.codegen.project.CodegenPackageSources; import org.drools.model.codegen.project.DroolsModelBuilder; @@ -140,9 +141,8 @@ protected Collection internalGenerate() { .flatMap(pkgSrc -> pkgSrc.getRuleUnits().stream()) .forEach(ru -> kieModuleModelWrapper.addRuleUnitConfig(ru, configs.get(ru.getCanonicalName()))); - // main codegen procedure (rule units, rule unit instances, queries, generated pojos) - RuleUnitMainCodegen ruleUnitCodegen = new RuleUnitMainCodegen(context(), ruleUnitGenerators, hotReloadMode); - generatedFiles.addAll(ruleUnitCodegen.generate()); + List errors = new ArrayList<>(); + List validQueries = validateQueries(errors); // dashboard for rule unit RuleUnitDashboardCodegen dashboardCodegen = new RuleUnitDashboardCodegen(context(), ruleUnitGenerators); @@ -150,13 +150,12 @@ protected Collection internalGenerate() { // "extended" procedure: REST + Event handlers + query dashboards if (context().hasRESTForGenerator(this)) { - Collection validQueries = ruleUnitCodegen.validQueries(); RuleUnitExtendedCodegen ruleUnitExtendedCodegen = new RuleUnitExtendedCodegen(context(), validQueries); generatedFiles.addAll(ruleUnitExtendedCodegen.generate()); } - if (!ruleUnitCodegen.errors().isEmpty()) { - throw new RuleCodegenError(ruleUnitCodegen.errors()); + if (!errors.isEmpty()) { + throw new RuleCodegenError(errors); } } else { LOGGER.info("No rule unit is present: generate KieRuntimeBuilder implementation."); @@ -168,6 +167,20 @@ protected Collection internalGenerate() { return generatedFiles; } + private List validateQueries(List errors) { + List validQueries = new ArrayList<>(); + for (RuleUnitGenerator ruleUnit : ruleUnitGenerators) { + for (QueryGenerator queryGenerator : ruleUnit.queries()) { + if (queryGenerator.validate()) { + validQueries.add(queryGenerator); + } else { + errors.add(queryGenerator.getError()); + } + } + } + return validQueries; + } + public RuleCodegen withHotReloadMode() { // fixme this is currently only used in test cases. Drop? this.hotReloadMode = true; return this; diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegenUtils.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegenUtils.java deleted file mode 100644 index 22e66798a0b..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleCodegenUtils.java +++ /dev/null @@ -1,77 +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.codegen.rules; - -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.kie.internal.ruleunit.RuleUnitDescription; - -import com.github.javaparser.ast.type.Type; - -import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType; -import static org.drools.model.codegen.execmodel.generator.DrlxParseUtil.toClassOrInterfaceType; - -public class RuleCodegenUtils { - - private RuleCodegenUtils() { - // utility class - } - - public static void setGeneric(Type type, RuleUnitDescription ruleUnit) { - type.asClassOrInterfaceType().setTypeArguments(toClassOrInterfaceType(ruleUnit.getCanonicalName())); - } - - public static void setGeneric(Type type, String typeArgument) { - type.asClassOrInterfaceType().setTypeArguments(parseClassOrInterfaceType(toNonPrimitiveType(typeArgument))); - } - - public static String toNonPrimitiveType(String type) { - switch (type) { - case "int": - return "Integer"; - case "long": - return "Long"; - case "double": - return "Double"; - case "float": - return "Float"; - case "short": - return "Short"; - case "byte": - return "Byte"; - case "char": - return "Character"; - case "boolean": - return "Boolean"; - default: - return type; - } - } - - public static String toCamelCase(String inputString) { - return Stream.of(inputString.split(" ")) - .map(s -> s.length() > 1 ? s.substring(0, 1).toUpperCase() + s.substring(1) : s.substring(0, 1).toUpperCase()) - .collect(Collectors.joining()); - } - - public static String toKebabCase(String inputString) { - return inputString.replaceAll("(.)(\\p{Upper})", "$1-$2").toLowerCase(); - } -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleObjectMapperCodegen.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleObjectMapperCodegen.java deleted file mode 100644 index 4f753f38ef0..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleObjectMapperCodegen.java +++ /dev/null @@ -1,43 +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.codegen.rules; - -import org.drools.codegen.common.GeneratedFile; -import org.kie.kogito.codegen.api.Generator; -import org.kie.kogito.codegen.api.context.KogitoBuildContext; -import org.kie.kogito.codegen.api.template.TemplatedGenerator; - -public class RuleObjectMapperCodegen { - - private final KogitoBuildContext context; - - public RuleObjectMapperCodegen(KogitoBuildContext context) { - this.context = context; - } - - GeneratedFile generate() { - TemplatedGenerator generator = TemplatedGenerator.builder() - .withTemplateBasePath(RuleCodegen.TEMPLATE_RULE_FOLDER) - .build(context, "KogitoObjectMapper"); - - return new GeneratedFile(Generator.REST_TYPE, - generator.generatedFilePath(), - generator.compilationUnitOrThrow().toString()); - } -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitExtendedCodegen.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitExtendedCodegen.java index d9e21468ef6..c4e6d93c603 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitExtendedCodegen.java +++ b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitExtendedCodegen.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import org.drools.codegen.common.GeneratedFile; import org.kie.kogito.codegen.api.context.KogitoBuildContext; @@ -28,25 +29,22 @@ public class RuleUnitExtendedCodegen { private final RuleUnitQueryDashboardCodegen dashboards; private final RuleUnitQueryEventCodegen events; - private final RuleUnitQueryRestCodegen rest; - private final RuleObjectMapperCodegen objectMapper; public RuleUnitExtendedCodegen( KogitoBuildContext context, Collection validQueries) { - this.rest = new RuleUnitQueryRestCodegen(validQueries); this.events = new RuleUnitQueryEventCodegen(context, validQueries); - this.dashboards = new RuleUnitQueryDashboardCodegen(context, rest.endpointGenerators()); - this.objectMapper = new RuleObjectMapperCodegen(context); + Collection endpointGenerators = validQueries.stream() + .map(QueryEndpointGenerator::new) + .collect(Collectors.toUnmodifiableList()); + this.dashboards = new RuleUnitQueryDashboardCodegen(context, endpointGenerators); } Collection generate() { List generatedFiles = new ArrayList<>(); generatedFiles.addAll(events.generate()); - generatedFiles.addAll(rest.generate()); generatedFiles.addAll(dashboards.generate()); - generatedFiles.add(objectMapper.generate()); return generatedFiles; } diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitGenerator.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitGenerator.java index c5ffe08ac09..0c6ee8be27c 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitGenerator.java +++ b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitGenerator.java @@ -20,13 +20,11 @@ import java.util.Collection; import java.util.List; -import java.util.Optional; import org.drools.model.codegen.execmodel.QueryModel; import org.drools.ruleunits.api.RuleUnit; import org.drools.ruleunits.api.conf.RuleUnitConfig; import org.drools.ruleunits.impl.AbstractRuleUnitDescription; -import org.drools.ruleunits.impl.GeneratedRuleUnitDescription; import org.kie.internal.ruleunit.RuleUnitDescription; import org.kie.kogito.codegen.api.context.KogitoBuildContext; @@ -77,14 +75,6 @@ public String typeName() { return typeName; } - public Optional pojo(RuleUnitHelper ruleUnitHelper) { - if (ruleUnit instanceof GeneratedRuleUnitDescription) { - return Optional.of(new RuleUnitPojoGenerator((GeneratedRuleUnitDescription) ruleUnit, ruleUnitHelper)); - } else { - return Optional.empty(); - } - } - public static ClassOrInterfaceType ruleUnitType(String canonicalName) { return new ClassOrInterfaceType(null, RuleUnit.class.getCanonicalName()) .setTypeArguments(new ClassOrInterfaceType(null, canonicalName)); diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitHelper.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitHelper.java deleted file mode 100644 index d66e14eb390..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitHelper.java +++ /dev/null @@ -1,57 +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.codegen.rules; - -import org.drools.ruleunits.impl.AssignableChecker; -import org.drools.ruleunits.impl.ReflectiveRuleUnitDescription; -import org.kie.internal.ruleunit.RuleUnitDescription; - -public class RuleUnitHelper { - private AssignableChecker defaultChecker; - private AssignableChecker assignableChecker; - - public RuleUnitHelper() { - } - - public RuleUnitHelper(ClassLoader cl, boolean hotReloadMode) { - this.defaultChecker = AssignableChecker.create(cl, hotReloadMode); - } - - public RuleUnitHelper(AssignableChecker assignableChecker) { - this.assignableChecker = assignableChecker; - } - - void initRuleUnitHelper(RuleUnitDescription ruleUnitDesc) { - if (ruleUnitDesc instanceof ReflectiveRuleUnitDescription) { - assignableChecker = ((ReflectiveRuleUnitDescription) ruleUnitDesc).getAssignableChecker(); - } else { - if (assignableChecker == null) { - assignableChecker = defaultChecker; - } - } - } - - public AssignableChecker getAssignableChecker() { - return assignableChecker; - } - - public boolean isAssignableFrom(Class source, Class target) { - return assignableChecker.isAssignableFrom(source, target); - } -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitMainCodegen.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitMainCodegen.java deleted file mode 100644 index 33ee944c5da..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitMainCodegen.java +++ /dev/null @@ -1,84 +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.codegen.rules; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.drools.codegen.common.GeneratedFile; -import org.drools.drl.parser.DroolsError; -import org.kie.kogito.codegen.api.context.KogitoBuildContext; - -/** - * Generates rule units, rule unit instances, pojos, queries - */ -public class RuleUnitMainCodegen { - private final KogitoBuildContext context; - private final Collection ruleUnitGenerators; - private final boolean hotReloadMode; - private final List validQueries; - private List errors = new ArrayList<>(); - - public RuleUnitMainCodegen(KogitoBuildContext context, Collection ruleUnitGenerators, boolean hotReloadMode) { - this.context = context; - this.ruleUnitGenerators = ruleUnitGenerators; - this.hotReloadMode = hotReloadMode; - this.validQueries = validateQueries(); - } - - Collection validQueries() { - return validQueries; - } - - Collection errors() { - return errors; - } - - Collection generate() { - List generatedFiles = new ArrayList<>(); - - RuleUnitHelper ruleUnitHelper = new RuleUnitHelper(context.getClassLoader(), hotReloadMode); - - for (RuleUnitGenerator ruleUnit : ruleUnitGenerators) { - ruleUnitHelper.initRuleUnitHelper(ruleUnit.getRuleUnitDescription()); - ruleUnit.pojo(ruleUnitHelper).ifPresent(p -> generatedFiles.add(p.generate())); - } - - for (QueryGenerator query : validQueries) { - generatedFiles.add(query.generate()); - } - return generatedFiles; - } - - private List validateQueries() { - List validQueries = new ArrayList<>(); - for (RuleUnitGenerator ruleUnit : ruleUnitGenerators) { - for (QueryGenerator queryGenerator : ruleUnit.queries()) { - if (queryGenerator.validate()) { - validQueries.add(queryGenerator); - } else { - errors.add(queryGenerator.getError()); - } - } - } - return validQueries; - } - -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitPojoGenerator.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitPojoGenerator.java deleted file mode 100644 index 4659172befb..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/java/org/kie/kogito/codegen/rules/RuleUnitPojoGenerator.java +++ /dev/null @@ -1,95 +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.codegen.rules; - -import java.util.Collections; - -import org.drools.codegen.common.GeneratedFile; -import org.drools.model.codegen.execmodel.JavaParserCompiler; -import org.drools.ruleunits.api.DataStore; -import org.drools.ruleunits.api.RuleUnitData; -import org.drools.ruleunits.impl.GeneratedRuleUnitDescription; -import org.kie.internal.ruleunit.RuleUnitVariable; - -import com.github.javaparser.StaticJavaParser; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.FieldDeclaration; -import com.github.javaparser.ast.body.VariableDeclarator; -import com.github.javaparser.ast.type.ClassOrInterfaceType; - -import static org.drools.util.ClassUtils.rawType; -import static org.kie.kogito.codegen.rules.RuleCodegen.RULE_TYPE; - -public class RuleUnitPojoGenerator implements RuleFileGenerator { - - private final GeneratedRuleUnitDescription ruleUnitDescription; - private final RuleUnitHelper ruleUnitHelper; - - public RuleUnitPojoGenerator(GeneratedRuleUnitDescription ruleUnitDescription, RuleUnitHelper ruleUnitHelper) { - this.ruleUnitDescription = ruleUnitDescription; - this.ruleUnitHelper = ruleUnitHelper; - } - - @Override - public GeneratedFile generate() { - String pojoSource = JavaParserCompiler.toPojoSource( - ruleUnitDescription.getPackageName(), - Collections.emptyList(), - Collections.emptyList(), - classOrInterfaceDeclaration()); - return new GeneratedFile(RULE_TYPE, - generatedFilePath(), - pojoSource); - } - - private ClassOrInterfaceDeclaration classOrInterfaceDeclaration() { - ClassOrInterfaceDeclaration c = - new ClassOrInterfaceDeclaration() - .setPublic(true) - .addImplementedType(RuleUnitData.class.getCanonicalName()) - .setName(ruleUnitDescription.getSimpleName()); - - for (RuleUnitVariable v : ruleUnitDescription.getUnitVarDeclarations()) { - ClassOrInterfaceType t = new ClassOrInterfaceType() - .setName(rawType(v.getType()).getCanonicalName()); - FieldDeclaration f = new FieldDeclaration(); - VariableDeclarator vd = new VariableDeclarator(t, v.getName()); - f.getVariables().add(vd); - if (v.isDataSource()) { - t.setTypeArguments(StaticJavaParser.parseType(v.getDataSourceParameterType().getCanonicalName())); - if (ruleUnitHelper.isAssignableFrom(DataStore.class, rawType(v.getType()))) { - vd.setInitializer("org.drools.ruleunits.api.DataSource.createStore()"); - } else { - vd.setInitializer("org.drools.ruleunits.api.DataSource.createSingleton()"); - } - } - c.addMember(f); - f.createGetter(); - if (v.setter() != null) { - f.createSetter(); - } - } - - return c; - } - - public String generatedFilePath() { - return ruleUnitDescription.getPackageName().replace('.', '/') + "/" + ruleUnitDescription.getSimpleName() + ".java"; - } -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/KogitoObjectMapperQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/KogitoObjectMapperQuarkusTemplate.java deleted file mode 100644 index e5dc9e080f0..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/KogitoObjectMapperQuarkusTemplate.java +++ /dev/null @@ -1,131 +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 $Package$; - -import java.util.List; - -import java.io.IOException; -import java.util.List; - -import com.fasterxml.jackson.databind.JavaType; -import javax.inject.Singleton; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.BeanProperty; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.deser.ContextualDeserializer; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.type.CollectionType; - -import org.drools.ruleunits.api.DataSource; -import org.drools.ruleunits.api.DataStore; -import org.drools.ruleunits.api.DataStream; -import org.drools.ruleunits.api.SingletonStore; - -import io.quarkus.jackson.ObjectMapperCustomizer; - -@Singleton -public class KogitoObjectMapper implements ObjectMapperCustomizer { - - public void customize(ObjectMapper mapper) { - mapper.registerModule(new KogitoModule()); - } - - public static class KogitoModule extends SimpleModule { - - public KogitoModule() { - addDefaultSerializers(); - addDefaultDeserializers(); - } - - private void addDefaultSerializers() { - } - - private void addDefaultDeserializers() { - addDeserializer( DataStream.class, new DataStreamDeserializer() ); - addDeserializer( DataStore.class, new DataStoreDeserializer() ); - addDeserializer( SingletonStore.class, new SingletonStoreDeserializer() ); - } - - public static class DataStreamDeserializer extends JsonDeserializer> implements ContextualDeserializer { - - private CollectionType collectionType; - - @Override - public DataStream deserialize( JsonParser jp, DeserializationContext ctxt) throws IOException { - DataStream stream = DataSource.createBufferedStream(16); - List list = ctxt.readValue( jp, collectionType ); - list.forEach( stream::append ); - return stream; - } - - @Override - public JsonDeserializer createContextual( DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { - CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, property.getType().containedType(0)); - DataStreamDeserializer deserializer = new DataStreamDeserializer(); - deserializer.collectionType = collectionType; - return deserializer; - } - } - - public static class DataStoreDeserializer extends JsonDeserializer> implements ContextualDeserializer { - - private CollectionType collectionType; - - @Override - public DataStore deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - DataStore store = DataSource.createStore(); - List list = ctxt.readValue( jp, collectionType ); - list.forEach( store::add ); - return store; - } - - @Override - public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { - CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, property.getType().containedType(0)); - DataStoreDeserializer deserializer = new DataStoreDeserializer(); - deserializer.collectionType = collectionType; - return deserializer; - } - } - - public static class SingletonStoreDeserializer extends JsonDeserializer> implements ContextualDeserializer { - - private JavaType javaType ; - - @Override - public SingletonStore deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - SingletonStore store = DataSource.createSingleton(); - store.set( ctxt.readValue( jp, javaType ) ); - return store; - } - - @Override - public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { - JavaType javaType = property.getType().containedType(0); - SingletonStoreDeserializer deserializer = new KogitoModule.SingletonStoreDeserializer(); - deserializer.javaType = javaType; - return deserializer; - } - } - } -} \ No newline at end of file diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/KogitoObjectMapperSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/KogitoObjectMapperSpringTemplate.java deleted file mode 100644 index 95599886fdf..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/KogitoObjectMapperSpringTemplate.java +++ /dev/null @@ -1,123 +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 $Package$; - -import java.util.List; - -import java.io.IOException; -import java.util.List; - -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.BeanProperty; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.deser.ContextualDeserializer; -import com.fasterxml.jackson.databind.type.CollectionType; - -import org.drools.ruleunits.api.DataSource; -import org.drools.ruleunits.api.DataStore; -import org.drools.ruleunits.api.DataStream; -import org.drools.ruleunits.api.SingletonStore; - -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; - -@SpringBootConfiguration -public class KogitoObjectMapper { - - @Bean - public Jackson2ObjectMapperBuilderCustomizer customizeObjectMapper() { - return new Jackson2ObjectMapperBuilderCustomizer() { - @Override - public void customize(Jackson2ObjectMapperBuilder builder) { - //addDefaultDeserializers - builder.deserializerByType(DataStream.class, new DataStreamDeserializer()); - builder.deserializerByType(DataStore.class, new DataStoreDeserializer()); - builder.deserializerByType(SingletonStore.class, new SingletonStoreDeserializer()); - } - }; - } - - public static class DataStreamDeserializer extends JsonDeserializer> implements ContextualDeserializer { - - private CollectionType collectionType; - - @Override - public DataStream deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - DataStream stream = DataSource.createBufferedStream(16); - List list = ctxt.readValue(jp, collectionType); - list.forEach(stream::append); - return stream; - } - - @Override - public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { - CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, property.getType().containedType(0)); - DataStreamDeserializer deserializer = new DataStreamDeserializer(); - deserializer.collectionType = collectionType; - return deserializer; - } - } - - public static class DataStoreDeserializer extends JsonDeserializer> implements ContextualDeserializer { - - private CollectionType collectionType; - - @Override - public DataStore deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - DataStore store = DataSource.createStore(); - List list = ctxt.readValue(jp, collectionType); - list.forEach(store::add); - return store; - } - - @Override - public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { - CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, property.getType().containedType(0)); - DataStoreDeserializer deserializer = new DataStoreDeserializer(); - deserializer.collectionType = collectionType; - return deserializer; - } - } - - public static class SingletonStoreDeserializer extends JsonDeserializer> implements ContextualDeserializer { - - private JavaType javaType; - - @Override - public SingletonStore deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - SingletonStore store = DataSource.createSingleton(); - store.set(ctxt.readValue(jp, javaType)); - return store; - } - - @Override - public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { - JavaType javaType = property.getType().containedType(0); - SingletonStoreDeserializer deserializer = new SingletonStoreDeserializer(); - deserializer.javaType = javaType; - return deserializer; - } - } -} \ No newline at end of file diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQueryJavaTemplate.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQueryJavaTemplate.java deleted file mode 100644 index b9c7d8ed0aa..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQueryJavaTemplate.java +++ /dev/null @@ -1,66 +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 com.myspace.demo; - -import java.util.List; -import java.util.Map; - -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import org.drools.ruleunits.api.RuleUnit; -import org.drools.ruleunits.api.RuleUnitInstance; - -import static java.util.stream.Collectors.toList; - -@Path("/$endpointName$") -public class $unit$Query$name$Endpoint { - - RuleUnit<$UnitType$> ruleUnit; - - public $unit$Query$name$Endpoint() { } - - public $unit$Query$name$Endpoint(RuleUnit<$UnitType$> ruleUnit) { - this.ruleUnit = ruleUnit; - } - - @POST() - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public List<$ReturnType$> executeQuery($UnitTypeDTO$ unitDTO) { - RuleUnitInstance<$UnitType$> instance = ruleUnit.createInstance(); - // Do not return the result directly to allow post execution codegen (like monitoring) - List<$ReturnType$> response = $unit$Query$name$.execute(instance); - instance.close(); - return response; - } - - @POST() - @Path("/first") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public $ReturnType$ executeQueryFirst($UnitTypeDTO$ unitDTO) { - List<$ReturnType$> results = executeQuery(unitDTO); - $ReturnType$ response = results.isEmpty() ? null : results.get(0); - return response; - } -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQueryQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQueryQuarkusTemplate.java deleted file mode 100644 index 59492c3e68e..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQueryQuarkusTemplate.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 com.myspace.demo; - -import java.util.List; -import java.util.Map; - -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import org.drools.ruleunits.api.RuleUnit; -import org.drools.ruleunits.api.RuleUnitInstance; - -import static java.util.stream.Collectors.toList; - -@Path("/$endpointName$") -public class $unit$Query$name$Endpoint { - - @javax.inject.Inject - RuleUnit<$UnitType$> ruleUnit; - - public $unit$Query$name$Endpoint() { } - - public $unit$Query$name$Endpoint(RuleUnit<$UnitType$> ruleUnit) { - this.ruleUnit = ruleUnit; - } - - @POST() - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public List<$ReturnType$> executeQuery($UnitTypeDTO$ unitDTO) { - RuleUnitInstance<$UnitType$> instance = ruleUnit.createInstance(); - // Do not return the result directly to allow post execution codegen (like monitoring) - List<$ReturnType$> response = $unit$Query$name$.execute(instance); - instance.close(); - return response; - } - - @POST() - @Path("/first") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public $ReturnType$ executeQueryFirst($UnitTypeDTO$ unitDTO) { - List<$ReturnType$> results = executeQuery(unitDTO); - $ReturnType$ response = results.isEmpty() ? null : results.get(0); - return response; - } -} diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQuerySpringTemplate.java b/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQuerySpringTemplate.java deleted file mode 100644 index 905456e1ab1..00000000000 --- a/kogito-codegen-modules/kogito-codegen-rules/src/main/resources/class-templates/rules/RestQuerySpringTemplate.java +++ /dev/null @@ -1,65 +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 com.myspace.demo; - -import java.util.List; -import java.util.Map; - -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.beans.factory.annotation.Autowired; - -import org.drools.ruleunits.api.RuleUnit; -import org.drools.ruleunits.api.RuleUnitInstance; - -import static java.util.stream.Collectors.toList; - -@RestController -@RequestMapping("/$endpointName$") -public class $unit$Query$name$Endpoint { - - @Autowired - RuleUnit<$UnitType$> ruleUnit; - - public $unit$Query$name$Endpoint() { } - - public $unit$Query$name$Endpoint(RuleUnit<$UnitType$> ruleUnit) { - this.ruleUnit = ruleUnit; - } - - @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) - public List<$ReturnType$> executeQuery(@RequestBody(required = true) $UnitTypeDTO$ unitDTO) { - RuleUnitInstance<$UnitType$> instance = ruleUnit.createInstance(); - // Do not return the result directly to allow post execution codegen (like monitoring) - List<$ReturnType$> response = $unit$Query$name$.execute(instance); - instance.close(); - return response; - } - - @PostMapping(value = "/first", produces = MediaType.APPLICATION_JSON_VALUE, consumes = - MediaType.APPLICATION_JSON_VALUE) - public $ReturnType$ executeQueryFirst(@RequestBody(required = true) $UnitTypeDTO$ unitDTO) { - List<$ReturnType$> results = executeQuery(unitDTO); - $ReturnType$ response = results.isEmpty() ? null : results.get(0); - return response; - } -} \ No newline at end of file diff --git a/kogito-codegen-modules/kogito-codegen-rules/src/test/java/org/kie/kogito/codegen/rules/RuleCodegenTest.java b/kogito-codegen-modules/kogito-codegen-rules/src/test/java/org/kie/kogito/codegen/rules/RuleCodegenTest.java index 24e4636fa9a..af70cbb1984 100644 --- a/kogito-codegen-modules/kogito-codegen-rules/src/test/java/org/kie/kogito/codegen/rules/RuleCodegenTest.java +++ b/kogito-codegen-modules/kogito-codegen-rules/src/test/java/org/kie/kogito/codegen/rules/RuleCodegenTest.java @@ -286,10 +286,10 @@ public void noObjectMapperWhenNoRest(KogitoBuildContext.Builder contextBuilder) Collection generatedFiles = incrementalRuleCodegen.withHotReloadMode().generate(); assertThat(generatedFiles).hasSizeGreaterThan(0); - if (contextBuilder.build().hasRESTGloballyAvailable()) { - assertThat(generatedFiles.stream()).anyMatch(f -> f.relativePath().endsWith("KogitoObjectMapper.java")); + if (contextBuilder.build().hasRest()) { + assertThat(generatedFiles.stream()).anyMatch(f -> f.relativePath().endsWith("ObjectMapper.java")); } else { - assertThat(generatedFiles.stream()).noneMatch(f -> f.relativePath().endsWith("KogitoObjectMapper.java")); + assertThat(generatedFiles.stream()).noneMatch(f -> f.relativePath().endsWith("ObjectMapper.java")); } } diff --git a/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java b/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java index 3930ababfca..9438aca8227 100644 --- a/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java +++ b/kogito-serverless-workflow/kogito-jq-expression/src/main/java/org/kie/kogito/expr/jq/JqExpression.java @@ -18,15 +18,20 @@ */ package org.kie.kogito.expr.jq; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; -import java.util.regex.Pattern; import org.kie.kogito.internal.process.runtime.KogitoProcessContext; import org.kie.kogito.jackson.utils.FunctionJsonNode; import org.kie.kogito.jackson.utils.JsonObjectUtils; import org.kie.kogito.jackson.utils.ObjectMapperFactory; +import org.kie.kogito.jackson.utils.PrefixJsonNode; import org.kie.kogito.process.expr.Expression; import org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils; import org.kie.kogito.serverless.workflow.utils.JsonNodeContext; @@ -36,27 +41,73 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import net.thisptr.jackson.jq.JsonQuery; import net.thisptr.jackson.jq.Output; import net.thisptr.jackson.jq.Scope; import net.thisptr.jackson.jq.Version; import net.thisptr.jackson.jq.exception.JsonQueryException; +import net.thisptr.jackson.jq.internal.javacc.ExpressionParser; +import net.thisptr.jackson.jq.internal.tree.FunctionCall; +import net.thisptr.jackson.jq.internal.tree.StringInterpolation; +import net.thisptr.jackson.jq.internal.tree.binaryop.BinaryOperatorExpression; public class JqExpression implements Expression { static final String LANG = "jq"; private static final Logger logger = LoggerFactory.getLogger(JqExpression.class); + private final Map, Collection> declaredFieldsMap = new ConcurrentHashMap<>(); + private final Map, Collection> allFieldsMap = new ConcurrentHashMap<>(); + private final Supplier scope; private final String expr; - private final Version version; - private JsonQuery query; + + private net.thisptr.jackson.jq.Expression internalExpr; private JsonQueryException validationError; + private static Field rhsField; + + static { + try { + rhsField = BinaryOperatorExpression.class.getDeclaredField("rhs"); + rhsField.setAccessible(true); + } catch (ReflectiveOperationException e) { + logger.warn("Unexpected exception while resolving rhs field", e); + } + } public JqExpression(Supplier scope, String expr, Version version) { this.expr = expr; this.scope = scope; - this.version = version; + try { + this.internalExpr = compile(version); + checkFunctionCall(internalExpr); + } catch (JsonQueryException ex) { + validationError = ex; + } + } + + private net.thisptr.jackson.jq.Expression compile(Version version) throws JsonQueryException { + net.thisptr.jackson.jq.Expression expression; + try { + expression = ExpressionParser.compile(expr, version); + } catch (JsonQueryException ex) { + expression = handleStringInterpolation(version).orElseThrow(() -> ex); + } + checkFunctionCall(expression); + return expression; + } + + private Optional handleStringInterpolation(Version version) { + if (!expr.startsWith("\"")) { + try { + net.thisptr.jackson.jq.Expression expression = ExpressionParser.compile("\"" + expr + "\"", version); + if (expression instanceof StringInterpolation) { + return Optional.of(expression); + } + } catch (JsonQueryException ex) { + // ignoring it + } + } + return Optional.empty(); } private interface TypedOutput extends Output { @@ -151,49 +202,75 @@ public void assign(Object target, Object value, KogitoProcessContext context) { private Scope getScope(KogitoProcessContext processInfo) { Scope childScope = Scope.newChildScope(scope.get()); - childScope.setValue(ExpressionHandlerUtils.SECRET_MAGIC, new FunctionJsonNode(ExpressionHandlerUtils::getSecret)); + childScope.setValue(ExpressionHandlerUtils.SECRET_MAGIC, new PrefixJsonNode<>(ExpressionHandlerUtils::getOptionalSecret)); childScope.setValue(ExpressionHandlerUtils.CONTEXT_MAGIC, new FunctionJsonNode(ExpressionHandlerUtils.getContextFunction(processInfo))); childScope.setValue(ExpressionHandlerUtils.CONST_MAGIC, ExpressionHandlerUtils.getConstants(processInfo)); return childScope; } private T eval(JsonNode context, Class returnClass, KogitoProcessContext processInfo) { + if (validationError != null) { + throw new IllegalArgumentException("Unable to evaluate content " + context + " using expr " + expr, validationError); + } + TypedOutput output = output(returnClass); try (JsonNodeContext jsonNode = JsonNodeContext.from(context, processInfo)) { - TypedOutput output = output(returnClass); - compile(); - query.apply(getScope(processInfo), jsonNode.getNode(), output); + internalExpr.apply(getScope(processInfo), jsonNode.getNode(), output); return JsonObjectUtils.convertValue(output.getResult(), returnClass); } catch (JsonQueryException e) { throw new IllegalArgumentException("Unable to evaluate content " + context + " using expr " + expr, e); } } - private void compile() throws JsonQueryException { - if (this.query == null) { - try { - this.query = JsonQuery.compile(expr, version); - } catch (JsonQueryException ex) { - validationError = ex; - throw ex; + @Override + public boolean isValid() { + return validationError == null; + } + + private void checkFunctionCall(net.thisptr.jackson.jq.Expression toCheck) throws JsonQueryException { + if (toCheck instanceof FunctionCall) { + toCheck.apply(scope.get(), ObjectMapperFactory.get().createObjectNode(), out -> { + }); + } else if (toCheck instanceof BinaryOperatorExpression) { + if (rhsField != null) { + try { + checkFunctionCall((net.thisptr.jackson.jq.Expression) rhsField.get(toCheck)); + } catch (ReflectiveOperationException e) { + logger.warn("Ignoring unexpected error {} while accesing field {} for class{} and expression {}", e.getMessage(), rhsField.getName(), toCheck.getClass(), expr); + } } + } else if (toCheck != null) { + for (Field f : getAllExprFields(toCheck)) + try { + checkFunctionCall((net.thisptr.jackson.jq.Expression) f.get(toCheck)); + } catch (ReflectiveOperationException e) { + logger.warn("Ignoring unexpected error {} while accesing field {} for class{} and expression {}", e.getMessage(), f.getName(), toCheck.getClass(), expr); + } } } - private static final Pattern JQ_FUNCTION_NAME = Pattern.compile("[a-zA-Z][a-zA-Z0-9_]*"); + private Collection getAllExprFields(net.thisptr.jackson.jq.Expression toCheck) { + return allFieldsMap.computeIfAbsent(toCheck.getClass(), this::getAllExprFields); + } - @Override - public boolean isValid() { - try { - compile(); - if (JQ_FUNCTION_NAME.matcher(expr).matches()) { - query.apply(scope.get(), ObjectMapperFactory.get().createObjectNode(), out -> { - }); + private Collection getAllExprFields(Class clazz) { + Collection fields = new HashSet<>(); + Class currentClass = clazz; + do { + fields.addAll(declaredFieldsMap.computeIfAbsent(currentClass.asSubclass(net.thisptr.jackson.jq.Expression.class), this::getDeclaredExprFields)); + currentClass = currentClass.getSuperclass(); + } while (net.thisptr.jackson.jq.Expression.class.isAssignableFrom(currentClass)); + return fields; + } + + private Collection getDeclaredExprFields(Class clazz) { + Collection fields = new HashSet<>(); + for (Field f : clazz.getDeclaredFields()) { + if (net.thisptr.jackson.jq.Expression.class.isAssignableFrom(f.getType())) { + f.setAccessible(true); + fields.add(f); } - } catch (JsonQueryException ex) { - logger.debug("Invalid expression {}", ex.getMessage()); - return false; } - return validationError == null; + return fields; } @Override diff --git a/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java b/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java index d5c11c6e8a8..b4806b5403b 100644 --- a/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java +++ b/kogito-serverless-workflow/kogito-jq-expression/src/test/java/org/kie/kogito/expr/jq/JqExpressionHandlerTest.java @@ -275,6 +275,12 @@ void testMagicWordsExpressions(String expression, String expectedResult, KogitoP assertThat(parsedExpression.eval(getObjectNode(), String.class, context)).isEqualTo(expectedResult); } + @Test + void testHardcodedStringIsValidOrNot() { + assertThat(ExpressionHandlerFactory.get("jq", "kserve_payload = to_kserve(image)").isValid()).isFalse(); + assertThat(ExpressionHandlerFactory.get("jq", "length .variable").isValid()).isTrue(); + } + private static Stream provideMagicWordExpressionsToTest() { return Stream.of( Arguments.of("$WORKFLOW.instanceId", "1111-2222-3333", getContext()), @@ -284,7 +290,7 @@ private static Stream provideMagicWordExpressionsToTest() { Arguments.of("$SECRET.none", "null", getContext()), Arguments.of("\"$SECRET.none\"", "$SECRET.none", getContext()), Arguments.of("$SECRET.lettersonly", "secretlettersonly", getContext()), - Arguments.of("$SECRET.dot.secret", "null", getContext()), + Arguments.of("$SECRET.dot.secret", "secretdotsecret", getContext()), Arguments.of("$SECRET.\"dot.secret\"", "secretdotsecret", getContext()), Arguments.of("$SECRET.\"dash-secret\"", "secretdashsecret", getContext()), Arguments.of("$CONST.someconstant", "value", getContext()), diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java index 5755de6d9cf..57952675962 100644 --- a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathExpression.java @@ -32,7 +32,6 @@ import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.PathNotFoundException; -import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; public class JsonPathExpression implements Expression { @@ -57,7 +56,7 @@ private static final String replaceMagic(String expr, String magic) { private Configuration getConfiguration(KogitoProcessContext context) { return Configuration .builder() - .mappingProvider(new JacksonMappingProvider()) + .mappingProvider(new JsonPathJacksonProvider()) .jsonProvider(new WorkflowJacksonJsonNodeJsonProvider(context)) .build(); } diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathJacksonProvider.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathJacksonProvider.java new file mode 100644 index 00000000000..528b4aa57ba --- /dev/null +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/JsonPathJacksonProvider.java @@ -0,0 +1,30 @@ +/* + * 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.expr.jsonpath; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; + +public class JsonPathJacksonProvider extends JacksonMappingProvider { + + @Override + public T map(Object source, Class targetType, Configuration configuration) { + return targetType.isAssignableFrom(source.getClass()) ? targetType.cast(source) : super.map(source, targetType, configuration); + } +} diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java index 43068ab3dce..f423bc5c9eb 100644 --- a/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/main/java/org/kie/kogito/expr/jsonpath/WorkflowJacksonJsonNodeJsonProvider.java @@ -21,6 +21,8 @@ import java.util.function.Function; import org.kie.kogito.internal.process.runtime.KogitoProcessContext; +import org.kie.kogito.jackson.utils.FunctionBaseJsonNode; +import org.kie.kogito.jackson.utils.PrefixJsonNode; import org.kie.kogito.serverless.workflow.utils.ExpressionHandlerUtils; import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider; @@ -37,10 +39,12 @@ public WorkflowJacksonJsonNodeJsonProvider(KogitoProcessContext context) { public Object getMapValue(Object obj, String key) { if (obj instanceof Function) { return ((Function) obj).apply(key); + } else if (obj instanceof FunctionBaseJsonNode) { + return ((FunctionBaseJsonNode) obj).get(key); } else { switch (key) { case "$" + ExpressionHandlerUtils.SECRET_MAGIC: - return (Function) ExpressionHandlerUtils::getSecret; + return new PrefixJsonNode<>(ExpressionHandlerUtils::getOptionalSecret); case "$" + ExpressionHandlerUtils.CONTEXT_MAGIC: return ExpressionHandlerUtils.getContextFunction(context); case "$" + ExpressionHandlerUtils.CONST_MAGIC: @@ -53,6 +57,6 @@ public Object getMapValue(Object obj, String key) { @Override public boolean isMap(Object obj) { - return super.isMap(obj) || obj instanceof Function; + return super.isMap(obj) || obj instanceof Function || obj instanceof FunctionBaseJsonNode; } } diff --git a/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java b/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java index 8d3a5720818..7d364f0ba12 100644 --- a/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java +++ b/kogito-serverless-workflow/kogito-jsonpath-expression/src/test/java/org/kie/kogito/expr/jsonpath/JsonPathExpressionHandlerTest.java @@ -238,8 +238,8 @@ private static Stream provideMagicWordExpressionsToTest() { return Stream.of( Arguments.of("$WORKFLOW.instanceId", "1111-2222-3333", getContext()), Arguments.of("$SECRET.lettersonly", "secretlettersonly", getContext()), - Arguments.of("$SECRET.none", "null", getContext()), - // Arguments.of("$SECRET.dot.secret", "null", getContext()), // exception due to missing object at path .dot + Arguments.of("$SECRET.none", "", getContext()), + Arguments.of("$SECRET.dot.secret", "secretdotsecret", getContext()), Arguments.of("$SECRET[\"dot.secret\"]", "secretdotsecret", getContext()), Arguments.of("$SECRET[\"dash-secret\"]", "secretdashsecret", getContext()), Arguments.of("$CONST.someconstant", "value", getContext()), diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java index 0432d83e5d0..edc9f52b098 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java @@ -128,6 +128,8 @@ private GeneratedInfo parseProcess() { .packageName(workflow.getMetadata() != null ? workflow.getMetadata().getOrDefault("package", DEFAULT_PACKAGE) : DEFAULT_PACKAGE) .visibility("Public") + .expressionLanguage(workflow.getExpressionLang()) + .metaData(Metadata.VARIABLE, DEFAULT_WORKFLOW_VAR) .variable(DEFAULT_WORKFLOW_VAR, new ObjectDataType(JsonNode.class), ObjectMapperFactory.listenerAware().createObjectNode()) .type(KogitoWorkflowProcess.SW_TYPE); ParserContext parserContext = diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/EventHandler.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/EventHandler.java index 25eefae43af..0a9c385b331 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/EventHandler.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/EventHandler.java @@ -33,10 +33,14 @@ import org.kie.kogito.serverless.workflow.parser.ServerlessWorkflowParser; import io.serverlessworkflow.api.Workflow; +import io.serverlessworkflow.api.actions.Action; import io.serverlessworkflow.api.events.OnEvents; import io.serverlessworkflow.api.states.EventState; +import static org.kie.kogito.serverless.workflow.parser.handlers.NodeFactoryUtils.eventBasedSplitNode; +import static org.kie.kogito.serverless.workflow.parser.handlers.NodeFactoryUtils.joinExclusiveNode; import static org.kie.kogito.serverless.workflow.parser.handlers.NodeFactoryUtils.startMessageNode; +import static org.kie.kogito.serverless.workflow.utils.TimeoutsConfigResolver.resolveEventTimeout; public class EventHandler extends CompositeContextNodeHandler { @@ -51,18 +55,45 @@ public void handleStart() { @Override public MakeNodeResult makeNode(RuleFlowNodeContainerFactory factory) { - MakeNodeResult currentBranch = joinNodes(factory, state.getOnEvents(), this::processOnEvent); - // ignore timeout for start states - return isStartState ? currentBranch : makeTimeoutNode(factory, currentBranch); + return joinNodes(factory, state.getOnEvents(), this::processOnEvent); } private MakeNodeResult processOnEvent(RuleFlowNodeContainerFactory factory, OnEvents onEvent) { - MakeNodeResult result = joinNodes(factory, - onEvent.getEventRefs(), (fact, onEventRef) -> filterAndMergeNode(fact, onEvent.getEventDataFilter(), isStartState ? ServerlessWorkflowParser.DEFAULT_WORKFLOW_VAR : getVarName(), - (f, inputVar, outputVar) -> buildEventNode(f, onEventRef, inputVar, outputVar))); - CompositeContextNodeFactory embeddedSubProcess = handleActions(makeCompositeNode(factory), onEvent.getActions()); - connect(result.getOutgoingNode(), embeddedSubProcess); - return new MakeNodeResult(result.getIncomingNode(), embeddedSubProcess); + if (isStartState) { + MakeNodeResult result = joinNodes(factory, + onEvent.getEventRefs(), (fact, onEventRef) -> filterAndMergeNode(fact, onEvent.getEventDataFilter(), ServerlessWorkflowParser.DEFAULT_WORKFLOW_VAR, + (f, inputVar, outputVar) -> buildEventNode(f, onEventRef, inputVar, outputVar))); + CompositeContextNodeFactory embeddedSubProcess = handleActions(makeCompositeNode(factory), onEvent.getActions()); + connect(result.getOutgoingNode(), embeddedSubProcess); + return new MakeNodeResult(result.getIncomingNode(), embeddedSubProcess); + } else { + String varName = getVarName(); + CompositeContextNodeFactory embeddedSubProcess = makeCompositeNode(factory); + NodeFactory startNode = embeddedSubProcess.startNode(parserContext.newId()).name("EmbeddedStart"); + JoinFactory joinNode = null; + String eventTimeout = resolveEventTimeout(state, workflow); + if (eventTimeout != null) { + // creating a split-join branch for the timer + SplitFactory splitNode = eventBasedSplitNode(embeddedSubProcess.splitNode(parserContext.newId()), Split.TYPE_XAND); + joinNode = joinExclusiveNode(embeddedSubProcess.joinNode(parserContext.newId())); + startNode = connect(startNode, splitNode); + createTimerNode(embeddedSubProcess, splitNode, joinNode, eventTimeout); + } + MakeNodeResult result = joinNodes(embeddedSubProcess, + onEvent.getEventRefs(), (fact, onEventRef) -> filterAndMergeNode(fact, onEvent.getEventDataFilter(), varName, + (f, inputVar, outputVar) -> buildEventNode(f, onEventRef, inputVar, outputVar))); + connect(startNode, result.getIncomingNode()); + NodeFactory currentNode = result.getOutgoingNode(); + for (Action action : onEvent.getActions()) { + currentNode = connect(currentNode, getActionNode(embeddedSubProcess, action, varName, true)); + } + if (joinNode != null) { + currentNode = connect(currentNode, joinNode); + } + connect(currentNode, embeddedSubProcess.endNode(parserContext.newId()).name("EmbeddedEnd").terminate(true)).done(); + handleErrors(parserContext.factory(), embeddedSubProcess); + return new MakeNodeResult(embeddedSubProcess); + } } private MakeNodeResult joinNodes(RuleFlowNodeContainerFactory factory, List events, BiFunction, T, MakeNodeResult> function) { diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/ForEachStateHandler.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/ForEachStateHandler.java index e06d5fac347..b9fab37eeac 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/ForEachStateHandler.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/ForEachStateHandler.java @@ -43,7 +43,7 @@ protected ForEachStateHandler(ForEachState state, Workflow workflow, ParserConte @Override protected MakeNodeResult makeNode(RuleFlowNodeContainerFactory factory) { ForEachNodeFactory result = - factory.forEachNode(parserContext.newId()).sequential(false).waitForCompletion(true).expressionLanguage(workflow.getExpressionLang()).collectionExpression(state.getInputCollection()) + factory.forEachNode(parserContext.newId()).sequential(false).waitForCompletion(true).collectionExpression(state.getInputCollection()) .outputVariable(FOR_EACH_OUTPUT_VARIABLE, new ObjectDataType(JsonNode.class)) .metaData(Metadata.VARIABLE, DEFAULT_WORKFLOW_VAR) .tempVariable(TEMP_OUTPUT_VAR, new ObjectDataType(JsonNode.class)); diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/StateHandler.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/StateHandler.java index 98eeda115a8..6ef53ad49c3 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/StateHandler.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/handlers/StateHandler.java @@ -33,7 +33,6 @@ import org.jbpm.ruleflow.core.Metadata; import org.jbpm.ruleflow.core.RuleFlowNodeContainerFactory; import org.jbpm.ruleflow.core.RuleFlowProcessFactory; -import org.jbpm.ruleflow.core.factory.AbstractCompositeNodeFactory; import org.jbpm.ruleflow.core.factory.ActionNodeFactory; import org.jbpm.ruleflow.core.factory.BoundaryEventNodeFactory; import org.jbpm.ruleflow.core.factory.CompositeContextNodeFactory; @@ -477,25 +476,19 @@ protected final EventDefinition eventDefinition(String eventName) { protected final MakeNodeResult makeTimeoutNode(RuleFlowNodeContainerFactory factory, MakeNodeResult notTimerBranch) { String eventTimeout = resolveEventTimeout(state, workflow); if (eventTimeout != null) { - if (notTimerBranch.getIncomingNode() == notTimerBranch.getOutgoingNode() && notTimerBranch.getIncomingNode() instanceof AbstractCompositeNodeFactory) { - // reusing composite - ((AbstractCompositeNodeFactory) notTimerBranch.getIncomingNode()).timeout(eventTimeout); - return notTimerBranch; - } else { - // creating a split-join branch for the timer - SplitFactory splitNode = eventBasedSplitNode(factory.splitNode(parserContext.newId()), Split.TYPE_XAND); - JoinFactory joinNode = joinExclusiveNode(factory.joinNode(parserContext.newId())); - connect(connect(splitNode, notTimerBranch), joinNode); - createTimerNode(factory, splitNode, joinNode, eventTimeout); - return new MakeNodeResult(splitNode, joinNode); - } + // creating a split-join branch for the timer + SplitFactory splitNode = eventBasedSplitNode(factory.splitNode(parserContext.newId()), Split.TYPE_XAND); + JoinFactory joinNode = joinExclusiveNode(factory.joinNode(parserContext.newId())); + connect(connect(splitNode, notTimerBranch), joinNode); + createTimerNode(factory, splitNode, joinNode, eventTimeout); + return new MakeNodeResult(splitNode, joinNode); } else { // No timeouts, returning the existing branch. return notTimerBranch; } } - private void createTimerNode(RuleFlowNodeContainerFactory factory, SplitFactory splitNode, JoinFactory joinNode, String eventTimeout) { + protected final void createTimerNode(RuleFlowNodeContainerFactory factory, SplitFactory splitNode, JoinFactory joinNode, String eventTimeout) { TimerNodeFactory eventTimeoutTimerNode = timerNode(factory.timerNode(parserContext.newId()), eventTimeout); connect(splitNode, eventTimeoutTimerNode); connect(eventTimeoutTimerNode, joinNode); diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolver.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolver.java index 10ace1d10ef..7a8bcb52a21 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolver.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolver.java @@ -21,15 +21,18 @@ import java.time.Duration; import java.time.format.DateTimeParseException; +import org.kie.kogito.process.expr.ExpressionHandlerFactory; + import io.serverlessworkflow.api.Workflow; import io.serverlessworkflow.api.interfaces.State; import io.serverlessworkflow.api.timeouts.TimeoutsDefinition; public class TimeoutsConfigResolver { - private static final String NON_NEGATIVE_DURATION_MUST_BE_PROVIDED = "When configured, it must be set with a greater than zero ISO 8601 time duration. For example PT30S."; + private static final String NON_NEGATIVE_DURATION_MUST_BE_PROVIDED = + "When configured, it must be set with a greater than zero ISO 8601 time duration. For example PT30S. Or a valid expression, for example $CONST.myDuration, where 'myDuration' is defined in the constant section of the workflow"; - private static final String INVALID_EVENT_TIMEOUT_FOR_STATE_ERROR = "An invalid \"eventTimeout\": \"%s\" configuration was provided for the state \"%s\" in the serverless workflow: \"%s\". " + + private static final String INVALID_EVENT_TIMEOUT_FOR_STATE_ERROR = "An invalid \"eventTimeout\": \"%s\" configuration was provided for the state \"%s\" in the serverless workflow: \"%s\"." + NON_NEGATIVE_DURATION_MUST_BE_PROVIDED; private static final String INVALID_EVENT_TIMEOUT_FOR_WORKFLOW_ERROR = "An invalid \"eventTimeout\": \"%s\" configuration was provided for the serverless workflow: \"%s\". " + @@ -45,7 +48,8 @@ public static String resolveEventTimeout(State state, Workflow workflow) { String.format(INVALID_EVENT_TIMEOUT_FOR_STATE_ERROR, timeouts.getEventTimeout(), state.getName(), - workflow.getName())); + workflow.getName()), + workflow.getExpressionLang()); return timeouts.getEventTimeout(); } else { timeouts = workflow.getTimeouts(); @@ -53,18 +57,21 @@ public static String resolveEventTimeout(State state, Workflow workflow) { validateDuration(timeouts.getEventTimeout(), String.format(INVALID_EVENT_TIMEOUT_FOR_WORKFLOW_ERROR, timeouts.getEventTimeout(), - workflow.getName())); + workflow.getName()), + workflow.getExpressionLang()); return timeouts.getEventTimeout(); } } return null; } - private static void validateDuration(String value, String message) { - try { - Duration.parse(value); - } catch (DateTimeParseException e) { - throw new IllegalArgumentException(message, e); + private static void validateDuration(String value, String message, String exprLanguage) { + if (!ExpressionHandlerFactory.get(exprLanguage, value).isValid()) { + try { + Duration.parse(value); + } catch (DateTimeParseException e) { + throw new IllegalArgumentException(message, e); + } } } } \ No newline at end of file diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/test/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolverTest.java b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/test/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolverTest.java index 0e638572b79..deb3dcb9895 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/test/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolverTest.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-builder/src/test/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolverTest.java @@ -97,6 +97,7 @@ private static State mockState(String name, String eventTimeout) { private static Workflow mockWorkflow(String name) { Workflow workflow = mock(Workflow.class); + doReturn("jq").when(workflow).getExpressionLang(); doReturn(name).when(workflow).getName(); return workflow; } diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java index c187dc6f828..d96afcd2c9d 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-executor-core/src/test/java/org/kie/kogito/serverless/workflow/executor/StaticFluentWorkflowApplicationTest.java @@ -189,11 +189,21 @@ void testJava() { @Test void testInterpolation() { + interpolation("\"My name is \\(.name) and my surname is \\(.surname)\""); + } + + @Test + void testAbreviatedInterpolation() { + interpolation("My name is \\(.name) and my surname is \\(.surname)"); + } + + private void interpolation(String text) { final String INTERPOLATION = "interpolation"; try (StaticWorkflowApplication application = StaticWorkflowApplication.create()) { - Workflow workflow = workflow("PlayingWithExpression").function(expr(INTERPOLATION, "\"My name is \\(.name)\"")) + Workflow workflow = workflow("PlayingWithExpression").function(expr(INTERPOLATION, text)) .start(operation().action(call(INTERPOLATION))).end().build(); - assertThat(application.execute(workflow, Collections.singletonMap("name", "Javierito")).getWorkflowdata().get("response").asText()).isEqualTo("My name is Javierito"); + assertThat(application.execute(workflow, Map.of("name", "Javierito", "surname", "unknown")).getWorkflowdata().get("response").asText()) + .isEqualTo("My name is Javierito and my surname is unknown"); } } diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java b/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java index 9d87627bddb..557cb6c86dd 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-runtime/src/main/java/org/kie/kogito/serverless/workflow/WorkflowWorkItemHandler.java @@ -26,7 +26,6 @@ import org.kie.kogito.internal.process.runtime.KogitoWorkItemHandler; import org.kie.kogito.internal.process.runtime.KogitoWorkItemManager; import org.kie.kogito.jackson.utils.JsonObjectUtils; -import org.kie.kogito.jackson.utils.ObjectMapperFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,10 +47,13 @@ public void executeWorkItem(KogitoWorkItem workItem, KogitoWorkItemManager manag protected static V buildBody(Map params, Class clazz) { for (Object obj : params.values()) { if (obj != null && clazz.isAssignableFrom(obj.getClass())) { + logger.trace("Invoking workitemhandler with value {}", obj); return clazz.cast(obj); } } - return ObjectMapperFactory.get().convertValue(params, clazz); + V value = JsonObjectUtils.convertValue(params, clazz); + logger.trace("Invoking workitemhandler with value {}", value); + return value; } @Override diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java b/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java index 615eef3d517..e727f96605a 100644 --- a/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java +++ b/kogito-serverless-workflow/kogito-serverless-workflow-utils/src/main/java/org/kie/kogito/serverless/workflow/utils/ExpressionHandlerUtils.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.Function; import org.jbpm.ruleflow.core.Metadata; @@ -53,8 +54,12 @@ public static JsonNode getConstants(KogitoProcessContext context) { return node == null ? NullNode.instance : node; } + public static Optional getOptionalSecret(String key) { + return ConfigResolverHolder.getConfigResolver().getConfigProperty(key, String.class); + } + public static String getSecret(String key) { - return ConfigResolverHolder.getConfigResolver().getConfigProperty(key, String.class).orElse(null); + return getOptionalSecret(key).orElse(null); } public static Function getContextFunction(KogitoProcessContext context) { diff --git a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoGenericContainer.java b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoGenericContainer.java index 7c046bea74d..facf38dd9f8 100644 --- a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoGenericContainer.java +++ b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoGenericContainer.java @@ -34,7 +34,6 @@ public KogitoGenericContainer(String containerName) { super(getImageName(containerName)); withStartupTimeout(CONTAINER_START_TIMEOUT); withLogConsumer(new Slf4jLogConsumer(LOGGER)); - withLogConsumer(f -> System.out.print(f.getUtf8String())); } public static String getImageName(String name) { diff --git a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKafkaContainer.java b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKafkaContainer.java index da5ef0b4e83..6bd3a3dce7e 100644 --- a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKafkaContainer.java +++ b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKafkaContainer.java @@ -47,7 +47,7 @@ public KogitoKafkaContainer() { withExposedPorts(KAFKA_PORT); withCreateContainerCmdModifier(cmd -> cmd.withEntrypoint("sh")); withCommand("-c", "while [ ! -f " + STARTER_SCRIPT + " ]; do sleep 0.1; done; " + STARTER_SCRIPT); - waitingFor(Wait.forLogMessage(".*Started Kafka API server.*", 1)); + waitingFor(Wait.forLogMessage(".*Started Kafka API server.*", 1).withStartupTimeout(Constants.CONTAINER_START_TIMEOUT)); } @Override diff --git a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKeycloakContainer.java b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKeycloakContainer.java index 811ec8eeb01..3cd8f46fa4f 100644 --- a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKeycloakContainer.java +++ b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoKeycloakContainer.java @@ -43,7 +43,7 @@ public KogitoKeycloakContainer() { withEnv("KEYCLOAK_ADMIN", USER); withEnv("KEYCLOAK_ADMIN_PASSWORD", PASSWORD); withClasspathResourceMapping("testcontainers/keycloak/kogito-realm.json", REALM_FILE, BindMode.READ_ONLY); - waitingFor(Wait.forLogMessage(".*Keycloak.*started.*", 1)); + waitingFor(Wait.forLogMessage(".*Keycloak.*started.*", 1).withStartupTimeout(Constants.CONTAINER_START_TIMEOUT)); withCommand("start-dev --import-realm"); } diff --git a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoRedisSearchContainer.java b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoRedisSearchContainer.java index f4adf9377a5..39433a57e63 100644 --- a/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoRedisSearchContainer.java +++ b/kogito-test-utils/src/main/java/org/kie/kogito/testcontainers/KogitoRedisSearchContainer.java @@ -29,7 +29,7 @@ public class KogitoRedisSearchContainer extends KogitoGenericContainer T deepCopy() { + return (T) this; + } + + @Override + public JsonNode get(int index) { + return MissingNode.getInstance(); + } + + @Override + public JsonNode path(String fieldName) { + return get(fieldName); + } + + @Override + public JsonNode path(int index) { + return MissingNode.getInstance(); + } + + @Override + protected JsonNode _at(JsonPointer ptr) { + return null; + } + + @Override + public JsonNodeType getNodeType() { + return JsonNodeType.OBJECT; + } + + @Override + public String asText() { + return null; + } + + @Override + public JsonNode findValue(String fieldName) { + return get(fieldName); + } + + @Override + public JsonNode findParent(String fieldName) { + return null; + } + + @Override + public List findValues(String fieldName, List foundSoFar) { + foundSoFar.add(findValue(fieldName)); + return foundSoFar; + } + + @Override + public List findValuesAsText(String fieldName, List foundSoFar) { + foundSoFar.add(findValue(fieldName).asText()); + return foundSoFar; + } + + @Override + public List findParents(String fieldName, List foundSoFar) { + foundSoFar.add(findParent(fieldName)); + return foundSoFar; + } + + @Override + public boolean equals(Object o) { + return true; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException { + // not serialize + } + + @Override + public void serializeWithType(JsonGenerator jgen, + SerializerProvider provider, + TypeSerializer typeSer) throws IOException { + // not serialize + } + +} \ No newline at end of file diff --git a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java index f61d160da50..3d2a67dfdad 100644 --- a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java +++ b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/FunctionJsonNode.java @@ -18,21 +18,11 @@ */ package org.kie.kogito.jackson.utils; -import java.io.IOException; -import java.util.List; import java.util.function.Function; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonPointer; -import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.jsontype.TypeSerializer; -import com.fasterxml.jackson.databind.node.BaseJsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeType; -import com.fasterxml.jackson.databind.node.MissingNode; -public class FunctionJsonNode extends BaseJsonNode { +public class FunctionJsonNode extends FunctionBaseJsonNode { private static final long serialVersionUID = 1L; private transient Function function; @@ -41,104 +31,8 @@ public FunctionJsonNode(Function function) { this.function = function; } - @Override - public JsonToken asToken() { - return JsonToken.START_OBJECT; - } - - @Override - public boolean isObject() { - return true; - } - - @Override - public T deepCopy() { - return (T) this; - } - - @Override - public JsonNode get(int index) { - return MissingNode.getInstance(); - } - - @Override - public JsonNode path(String fieldName) { - return get(fieldName); - } - - @Override - public JsonNode path(int index) { - return MissingNode.getInstance(); - } - - @Override - protected JsonNode _at(JsonPointer ptr) { - return null; - } - - @Override - public JsonNodeType getNodeType() { - return JsonNodeType.OBJECT; - } - - @Override - public String asText() { - return null; - } - - @Override - public JsonNode findValue(String fieldName) { - return get(fieldName); - } - @Override public JsonNode get(String fieldName) { return JsonObjectUtils.fromValue(function.apply(fieldName)); } - - @Override - public JsonNode findParent(String fieldName) { - return null; - } - - @Override - public List findValues(String fieldName, List foundSoFar) { - foundSoFar.add(findValue(fieldName)); - return foundSoFar; - } - - @Override - public List findValuesAsText(String fieldName, List foundSoFar) { - foundSoFar.add(findValue(fieldName).asText()); - return foundSoFar; - } - - @Override - public List findParents(String fieldName, List foundSoFar) { - foundSoFar.add(findParent(fieldName)); - return foundSoFar; - } - - @Override - public boolean equals(Object o) { - return true; - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException { - // not serialize - } - - @Override - public void serializeWithType(JsonGenerator jgen, - SerializerProvider provider, - TypeSerializer typeSer) throws IOException { - // not serialize - } - -} \ No newline at end of file +} diff --git a/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/PrefixJsonNode.java b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/PrefixJsonNode.java new file mode 100644 index 00000000000..0793e849d6f --- /dev/null +++ b/kogito-workitems/kogito-jackson-utils/src/main/java/org/kie/kogito/jackson/utils/PrefixJsonNode.java @@ -0,0 +1,59 @@ +/* + * 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.jackson.utils; + +import java.util.Optional; +import java.util.function.Function; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; + +public class PrefixJsonNode extends FunctionBaseJsonNode { + + private static final long serialVersionUID = 1L; + + private transient final String prefix; + private transient final Function> function; + private transient Optional value; + + public PrefixJsonNode(Function> function) { + this(null, function); + } + + public PrefixJsonNode(String prefix, Function> function) { + this.prefix = prefix; + this.function = function; + this.value = prefix == null ? Optional.empty() : function.apply(prefix); + } + + @Override + public JsonNodeType getNodeType() { + return value.isPresent() ? JsonNodeType.STRING : JsonNodeType.OBJECT; + } + + @Override + public String asText() { + return value.map(Object::toString).orElse(null); + } + + @Override + public JsonNode get(String fieldName) { + return new PrefixJsonNode<>(prefix == null ? fieldName : prefix + "." + fieldName, function); + } +} diff --git a/pom.xml b/pom.xml index 4f8a22ef85a..88e1eaaf5c9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,10 +3,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - org.jboss - jboss-parent - 39 - + org.apache + apache + 30 4.0.0 @@ -18,12 +17,11 @@ Kogito Runtimes Kogito Runtimes - http://kogito.kie.org 2019 - JBoss by Red Hat - http://www.jboss.org/ + The Apache Software Foundation + https://apache.org/ @@ -35,9 +33,9 @@ - scm:git:https://github.com/kiegroup/kogito-runtimes.git - scm:git:git@github.com:kiegroup/kogito-runtimes.git - https://github.com/kiegroup/kogito-runtimes + scm:git:https://github.com/apache/incubator-kie-kogito-runtimes.git + scm:git:git@github.com:apache/incubator-kie-kogito-runtimes.git + https://github.com/apache/incubator-kie-kogito-runtimes @@ -59,14 +57,14 @@ - jboss-releases-repository - JBoss Releases Repository - https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ + apache-release-staging-repository + Apache Release Staging Repository + https://repository.apache.org/service/local/staging/deploy/maven2 - jboss-snapshots-repository - JBoss Snapshot Repository - https://repository.jboss.org/nexus/content/repositories/snapshots/ + apache-snapshots-repository + Apache Snapshot Repository + https://repository.apache.org/content/repositories/snapshots/ @@ -74,9 +72,9 @@ - jboss-public-repository-group - JBoss Public Repository Group - https://repository.jboss.org/nexus/content/groups/public/ + apache-public-repository-group + Apache Public Repository Group + https://repository.apache.org/content/groups/public/ default true @@ -92,10 +90,10 @@ + first repository the Apache Nexus would be contacted first and since it is quite slow it slows down the build. + We use Apache Nexus repo only to download our SNAPSHOTs. --> central Central Repository https://repo.maven.apache.org/maven2 @@ -105,9 +103,9 @@ - jboss-public-repository-group - JBoss Public Repository Group - https://repository.jboss.org/nexus/content/groups/public/ + apache-public-repository-group + Apache Public Repository Group + https://repository.apache.org/content/groups/public/ true diff --git a/quarkus/addons/common/reactive-messaging/pom.xml b/quarkus/addons/common/reactive-messaging/pom.xml index 798a42c46d6..9d48f6df6de 100644 --- a/quarkus/addons/common/reactive-messaging/pom.xml +++ b/quarkus/addons/common/reactive-messaging/pom.xml @@ -37,6 +37,27 @@ io.smallrye.reactive smallrye-reactive-messaging-api + + + io.quarkiverse.reactivemessaging.http + quarkus-reactive-messaging-http + true + + + jakarta.ws.rs + jakarta.ws.rs-api + true + + + io.quarkus + quarkus-junit5 + test + + + org.assertj + assertj-core + test + \ No newline at end of file diff --git a/quarkus/addons/messaging/common/src/main/java/org/kie/kogito/addon/quarkus/messaging/common/message/CloudEventHttpOutgoingDecorator.java b/quarkus/addons/common/reactive-messaging/src/main/java/org/kie/kogito/addon/quarkus/common/reactive/messaging/http/CloudEventHttpOutgoingDecorator.java similarity index 96% rename from quarkus/addons/messaging/common/src/main/java/org/kie/kogito/addon/quarkus/messaging/common/message/CloudEventHttpOutgoingDecorator.java rename to quarkus/addons/common/reactive-messaging/src/main/java/org/kie/kogito/addon/quarkus/common/reactive/messaging/http/CloudEventHttpOutgoingDecorator.java index 93dc4b8786a..4ff805195c2 100644 --- a/quarkus/addons/messaging/common/src/main/java/org/kie/kogito/addon/quarkus/messaging/common/message/CloudEventHttpOutgoingDecorator.java +++ b/quarkus/addons/common/reactive-messaging/src/main/java/org/kie/kogito/addon/quarkus/common/reactive/messaging/http/CloudEventHttpOutgoingDecorator.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.kie.kogito.addon.quarkus.messaging.common.message; +package org.kie.kogito.addon.quarkus.common.reactive.messaging.http; import javax.ws.rs.core.HttpHeaders; diff --git a/quarkus/addons/messaging/common/src/test/java/org/kie/kogito/addon/quarkus/messaging/common/message/CloudEventHttpOutgoingDecoratorTest.java b/quarkus/addons/common/reactive-messaging/src/test/java/org/kie/kogito/addon/quarkus/messaging/common/message/http/CloudEventHttpOutgoingDecoratorTest.java similarity index 79% rename from quarkus/addons/messaging/common/src/test/java/org/kie/kogito/addon/quarkus/messaging/common/message/CloudEventHttpOutgoingDecoratorTest.java rename to quarkus/addons/common/reactive-messaging/src/test/java/org/kie/kogito/addon/quarkus/messaging/common/message/http/CloudEventHttpOutgoingDecoratorTest.java index 4c8e16dd17c..72b4d3200a6 100644 --- a/quarkus/addons/messaging/common/src/test/java/org/kie/kogito/addon/quarkus/messaging/common/message/CloudEventHttpOutgoingDecoratorTest.java +++ b/quarkus/addons/common/reactive-messaging/src/test/java/org/kie/kogito/addon/quarkus/messaging/common/message/http/CloudEventHttpOutgoingDecoratorTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.kie.kogito.addon.quarkus.messaging.common.message; +package org.kie.kogito.addon.quarkus.messaging.common.message.http; import java.util.Collections; import java.util.Optional; @@ -26,9 +26,8 @@ import org.eclipse.microprofile.reactive.messaging.Message; import org.junit.jupiter.api.Test; -import org.kie.kogito.KogitoGAV; import org.kie.kogito.addon.quarkus.common.reactive.messaging.MessageDecoratorProvider; -import org.kie.kogito.config.ConfigBean; +import org.kie.kogito.addon.quarkus.common.reactive.messaging.http.CloudEventHttpOutgoingDecorator; import io.quarkus.reactivemessaging.http.runtime.OutgoingHttpMetadata; import io.quarkus.test.junit.QuarkusTest; @@ -44,25 +43,6 @@ class CloudEventHttpOutgoingDecoratorTest { @Produces CloudEventHttpOutgoingDecorator decorator = new CloudEventHttpOutgoingDecorator(); - @Produces - ConfigBean configBean = new ConfigBean() { - - @Override - public boolean useCloudEvents() { - return true; - } - - @Override - public String getServiceUrl() { - return null; - } - - @Override - public Optional getGav() { - return Optional.empty(); - } - }; - @Test void verifyOutgoingHttpMetadataIsSet() { Message message = provider.decorate(Message.of("pepe")); diff --git a/quarkus/addons/events/mongodb/runtime/src/main/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisher.java b/quarkus/addons/events/mongodb/runtime/src/main/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisher.java index c40be271312..acc045bf570 100644 --- a/quarkus/addons/events/mongodb/runtime/src/main/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisher.java +++ b/quarkus/addons/events/mongodb/runtime/src/main/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisher.java @@ -44,10 +44,6 @@ public class QuarkusMongoDBEventPublisher extends MongoDBEventPublisher { @ConfigProperty(name = "kogito.events.usertasks.enabled", defaultValue = "true") boolean quarkusEnableUserTasksEvents; - @Inject - @ConfigProperty(name = "kogito.events.variables.enabled", defaultValue = "true") - boolean quarkusEnableVariablesEvents; - @Inject @ConfigProperty(name = "kogito.events.database", defaultValue = "kogito-events") String quarkusEventsDatabaseName; @@ -60,10 +56,6 @@ public class QuarkusMongoDBEventPublisher extends MongoDBEventPublisher { @ConfigProperty(name = "kogito.events.usertasks.collection", defaultValue = "kogitousertaskinstancesevents") String quarkusUserTasksEventsCollectionName; - @Inject - @ConfigProperty(name = "kogito.events.variables.collection", defaultValue = "kogitovariablesevents") - String quarkusVariablesEventsCollectionName; - @PostConstruct public void setupQuarkusMongoDBEventPublisher() { super.configure(); @@ -89,11 +81,6 @@ protected boolean userTasksEvents() { return this.quarkusEnableUserTasksEvents; } - @Override - protected boolean variablesEvents() { - return this.quarkusEnableVariablesEvents; - } - @Override protected String eventsDatabaseName() { return this.quarkusEventsDatabaseName; @@ -108,9 +95,4 @@ protected String processInstancesEventsCollection() { protected String userTasksEventsCollection() { return this.quarkusUserTasksEventsCollectionName; } - - @Override - protected String variablesEventsCollection() { - return this.quarkusVariablesEventsCollectionName; - } } diff --git a/quarkus/addons/events/mongodb/runtime/src/test/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisherTest.java b/quarkus/addons/events/mongodb/runtime/src/test/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisherTest.java index a34f13890cb..9d95cf44664 100644 --- a/quarkus/addons/events/mongodb/runtime/src/test/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisherTest.java +++ b/quarkus/addons/events/mongodb/runtime/src/test/java/org/kie/kogito/events/mongodb/QuarkusMongoDBEventPublisherTest.java @@ -72,11 +72,6 @@ void userTasksEvents() { assertFalse(publisher.userTasksEvents()); } - @Test - void variablesEvents() { - assertFalse(publisher.variablesEvents()); - } - @Test void eventsDatabaseName() { assertEquals("testDB", publisher.eventsDatabaseName()); @@ -92,8 +87,4 @@ void userTasksEventsCollection() { assertEquals("testUTCollection", publisher.userTasksEventsCollection()); } - @Test - void variablesEventsCollection() { - assertEquals("testVCollection", publisher.variablesEventsCollection()); - } } diff --git a/quarkus/addons/events/process/deployment/pom.xml b/quarkus/addons/events/process/deployment/pom.xml index c39e5c7852f..d09dcf06787 100644 --- a/quarkus/addons/events/process/deployment/pom.xml +++ b/quarkus/addons/events/process/deployment/pom.xml @@ -42,6 +42,10 @@ org.kie.kogito kogito-addons-quarkus-common-deployment + + org.kie.kogito + kogito-quarkus-common-deployment + diff --git a/quarkus/addons/events/process/deployment/src/main/java/org/kie/kogito/events/process/deployment/KogitoAddOnEventProcessProcessor.java b/quarkus/addons/events/process/deployment/src/main/java/org/kie/kogito/events/process/deployment/KogitoAddOnEventProcessProcessor.java index 33b2a87ae41..4f2fd414e3d 100644 --- a/quarkus/addons/events/process/deployment/src/main/java/org/kie/kogito/events/process/deployment/KogitoAddOnEventProcessProcessor.java +++ b/quarkus/addons/events/process/deployment/src/main/java/org/kie/kogito/events/process/deployment/KogitoAddOnEventProcessProcessor.java @@ -18,9 +18,15 @@ */ package org.kie.kogito.events.process.deployment; +import org.kie.kogito.addon.quarkus.common.reactive.messaging.http.CloudEventHttpOutgoingDecorator; import org.kie.kogito.quarkus.addons.common.deployment.KogitoCapability; import org.kie.kogito.quarkus.addons.common.deployment.OneOfCapabilityKogitoAddOnProcessor; +import org.kie.kogito.quarkus.common.deployment.KogitoBuildContextBuildItem; +import org.kie.kogito.quarkus.config.KogitoBuildTimeConfig; +import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.arc.processor.DotNames; +import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.FeatureBuildItem; @@ -37,4 +43,11 @@ FeatureBuildItem feature() { return new FeatureBuildItem(FEATURE); } + @BuildStep + void httpMessageDecorator(BuildProducer beanBuildItem, KogitoBuildTimeConfig buildTimeConfig, KogitoBuildContextBuildItem kogitoContext) { + if (buildTimeConfig.useCloudEvents && kogitoContext.getKogitoBuildContext().hasClassAvailable("io.quarkus.reactivemessaging.http.runtime.OutgoingHttpMetadata")) { + beanBuildItem.produce(AdditionalBeanBuildItem.builder().addBeanClass(CloudEventHttpOutgoingDecorator.class).setDefaultScope(DotNames.APPLICATION_SCOPED).build()); + } + } + } diff --git a/quarkus/addons/events/process/runtime/pom.xml b/quarkus/addons/events/process/runtime/pom.xml index d6db8478b7b..6f566021afd 100644 --- a/quarkus/addons/events/process/runtime/pom.xml +++ b/quarkus/addons/events/process/runtime/pom.xml @@ -65,6 +65,10 @@ io.quarkus quarkus-arc + + org.kie.kogito + kogito-quarkus-common + org.slf4j diff --git a/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/config/EventsRuntimeConfig.java b/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/config/EventsRuntimeConfig.java new file mode 100644 index 00000000000..5e78b3de9b9 --- /dev/null +++ b/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/config/EventsRuntimeConfig.java @@ -0,0 +1,58 @@ +/* + * 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.events.config; + +import io.quarkus.runtime.annotations.ConfigItem; +import io.quarkus.runtime.annotations.ConfigPhase; +import io.quarkus.runtime.annotations.ConfigRoot; + +@ConfigRoot(name = "kogito", phase = ConfigPhase.RUN_TIME, prefix = "events") +public class EventsRuntimeConfig { + + /** + * Enable publishing processes instances events + */ + @ConfigItem(name = "processinstances.enabled", defaultValue = "true") + boolean processInstancesEventsEnabled; + + /** + * Enable publishing processes definition events + */ + @ConfigItem(name = "processdefinitions.enabled", defaultValue = "true") + boolean processDefinitionEventsEnabled; + + /** + * Enable publishing user task instances events + */ + @ConfigItem(name = "usertasks.enabled", defaultValue = "true") + boolean userTasksEventsEnabled; + + public boolean isProcessInstancesEventsEnabled() { + return processInstancesEventsEnabled; + } + + public boolean isProcessDefinitionEventsEnabled() { + return processDefinitionEventsEnabled; + } + + public boolean isUserTasksEventsEnabled() { + return userTasksEventsEnabled; + } + +} diff --git a/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/process/ReactiveMessagingEventPublisher.java b/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/process/ReactiveMessagingEventPublisher.java index 3dfa2679aff..225f55eb4e1 100644 --- a/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/process/ReactiveMessagingEventPublisher.java +++ b/quarkus/addons/events/process/runtime/src/main/java/org/kie/kogito/events/process/ReactiveMessagingEventPublisher.java @@ -19,7 +19,6 @@ package org.kie.kogito.events.process; import java.util.Collection; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -28,25 +27,22 @@ import javax.inject.Inject; import javax.inject.Singleton; -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.kie.kogito.addon.quarkus.common.reactive.messaging.MessageDecoratorProvider; import org.kie.kogito.event.DataEvent; import org.kie.kogito.event.EventPublisher; +import org.kie.kogito.events.config.EventsRuntimeConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; +import io.smallrye.reactive.messaging.MutinyEmitter; import io.smallrye.reactive.messaging.providers.locals.ContextAwareMessage; @Singleton public class ReactiveMessagingEventPublisher implements EventPublisher { - private static final String PI_TOPIC_NAME = "kogito-processinstances-events"; - private static final String UI_TOPIC_NAME = "kogito-usertaskinstances-events"; - private static final String VI_TOPIC_NAME = "kogito-variables-events"; private static final Logger logger = LoggerFactory.getLogger(ReactiveMessagingEventPublisher.class); @@ -54,28 +50,18 @@ public class ReactiveMessagingEventPublisher implements EventPublisher { ObjectMapper json; @Inject - @Channel(PI_TOPIC_NAME) - Emitter processInstancesEventsEmitter; + @Channel(PROCESS_INSTANCES_TOPIC_NAME) + MutinyEmitter processInstancesEventsEmitter; @Inject - @Channel(UI_TOPIC_NAME) - Emitter userTasksEventsEmitter; + @Channel(PROCESS_DEFINITIONS_TOPIC_NAME) + MutinyEmitter processDefinitionEventsEmitter; @Inject - @Channel(VI_TOPIC_NAME) - Emitter variablesEventsEmitter; - - @Inject - @ConfigProperty(name = "kogito.events.processinstances.enabled") - Optional processInstancesEvents; - - @Inject - @ConfigProperty(name = "kogito.events.usertasks.enabled") - Optional userTasksEvents; - + @Channel(USER_TASK_INSTANCES_TOPIC_NAME) + MutinyEmitter userTasksEventsEmitter; @Inject - @ConfigProperty(name = "kogito.events.variables.enabled") - Optional variablesEvents; + EventsRuntimeConfig eventsRuntimeConfig; @Inject Instance decoratorProviderInstance; @@ -89,20 +75,31 @@ public void init() { @Override public void publish(DataEvent event) { + switch (event.getType()) { - case "ProcessInstanceEvent": - if (processInstancesEvents.orElse(true)) { - publishToTopic(event, processInstancesEventsEmitter, PI_TOPIC_NAME); + case "ProcessDefinitionEvent": + if (eventsRuntimeConfig.isProcessDefinitionEventsEnabled()) { + publishToTopic(event, processDefinitionEventsEmitter, PROCESS_DEFINITIONS_TOPIC_NAME); } break; - case "UserTaskInstanceEvent": - if (userTasksEvents.orElse(true)) { - publishToTopic(event, userTasksEventsEmitter, UI_TOPIC_NAME); + case "ProcessInstanceErrorDataEvent": + case "ProcessInstanceNodeDataEvent": + case "ProcessInstanceSLADataEvent": + case "ProcessInstanceStateDataEvent": + case "ProcessInstanceVariableDataEvent": + if (eventsRuntimeConfig.isProcessInstancesEventsEnabled()) { + publishToTopic(event, processInstancesEventsEmitter, PROCESS_INSTANCES_TOPIC_NAME); } break; - case "VariableInstanceEvent": - if (variablesEvents.orElse(true)) { - publishToTopic(event, variablesEventsEmitter, VI_TOPIC_NAME); + + case "UserTaskInstanceAssignmentDataEvent": + case "UserTaskInstanceAttachmentDataEvent": + case "UserTaskInstanceCommentDataEvent": + case "UserTaskInstanceDeadlineDataEvent": + case "UserTaskInstanceStateDataEvent": + case "UserTaskInstanceVariableDataEvent": + if (eventsRuntimeConfig.isUserTasksEventsEnabled()) { + publishToTopic(event, userTasksEventsEmitter, USER_TASK_INSTANCES_TOPIC_NAME); } break; default: @@ -117,18 +114,14 @@ public void publish(Collection> events) { } } - protected void publishToTopic(DataEvent event, Emitter emitter, String topic) { - if (emitter.hasRequests()) { - logger.debug("Emitter {} is not ready to send messages", topic); - } - + protected void publishToTopic(DataEvent event, MutinyEmitter emitter, String topic) { logger.debug("About to publish event {} to topic {}", event, topic); try { String eventString = json.writeValueAsString(event); + Message message = decorateMessage(ContextAwareMessage.of(eventString)); + logger.debug("Event payload '{}'", eventString); - emitter.send(decorateMessage(ContextAwareMessage.of(eventString) - .withAck(() -> onAck(event, topic)) - .withNack(reason -> onNack(reason, event, topic)))); + emitter.sendMessageAndAwait(message); } catch (Exception e) { logger.error("Error while creating event to topic {} for event {}", topic, event, e); diff --git a/quarkus/addons/jobs/knative-eventing/runtime/src/main/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsService.java b/quarkus/addons/jobs/knative-eventing/runtime/src/main/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsService.java index 6c603f3b5ca..d11d0b35c70 100644 --- a/quarkus/addons/jobs/knative-eventing/runtime/src/main/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsService.java +++ b/quarkus/addons/jobs/knative-eventing/runtime/src/main/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsService.java @@ -27,7 +27,7 @@ import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; import org.eclipse.microprofile.reactive.messaging.Message; -import org.kie.kogito.addon.quarkus.messaging.common.message.CloudEventHttpOutgoingDecorator; +import org.kie.kogito.addon.quarkus.common.reactive.messaging.http.CloudEventHttpOutgoingDecorator; import org.kie.kogito.jobs.messaging.quarkus.AbstractReactiveMessagingJobsService; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/quarkus/addons/jobs/knative-eventing/runtime/src/test/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsServiceTest.java b/quarkus/addons/jobs/knative-eventing/runtime/src/test/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsServiceTest.java index ecfd25301ff..74bd0c9b920 100644 --- a/quarkus/addons/jobs/knative-eventing/runtime/src/test/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsServiceTest.java +++ b/quarkus/addons/jobs/knative-eventing/runtime/src/test/java/org/kie/kogito/jobs/knative/eventing/quarkus/KnativeEventingJobsServiceTest.java @@ -34,7 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -import static org.kie.kogito.addon.quarkus.messaging.common.message.CloudEventHttpOutgoingDecorator.CLOUD_EVENTS_CONTENT_TYPE; +import static org.kie.kogito.addon.quarkus.common.reactive.messaging.http.CloudEventHttpOutgoingDecorator.CLOUD_EVENTS_CONTENT_TYPE; class KnativeEventingJobsServiceTest extends AbstractReactiveMessagingJobsServiceTest { diff --git a/quarkus/addons/knative/eventing/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactory.java b/quarkus/addons/knative/eventing/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactory.java index b20a22685cf..088e353ba9c 100644 --- a/quarkus/addons/knative/eventing/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactory.java +++ b/quarkus/addons/knative/eventing/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactory.java @@ -42,9 +42,9 @@ public final class KnativeEventingConfigSourceFactory implements ConfigSourceFac private static final String PROCESS_INSTANCES_EVENTS = "kogito-processinstances-events"; - private static final String USER_TASK_INSTANCES_EVENTS = "kogito-usertaskinstances-events"; + private static final String PROCESS_DEFINITIONS_EVENTS = "kogito-processdefinitions-events"; - private static final String VARIABLE_EVENTS = "kogito-variables-events"; + private static final String USER_TASK_INSTANCES_EVENTS = "kogito-usertaskinstances-events"; private static final String QUARKUS_HTTP_CONNECTOR = "quarkus-http"; @@ -74,8 +74,8 @@ public Iterable getConfigSources(ConfigSourceContext context) { if (includeProcessEvents(context)) { addOutgoingConnector(configuration, PROCESS_INSTANCES_EVENTS); + addOutgoingConnector(configuration, PROCESS_DEFINITIONS_EVENTS); addOutgoingConnector(configuration, USER_TASK_INSTANCES_EVENTS); - addOutgoingConnector(configuration, VARIABLE_EVENTS); } final String sinkUrl = context.getValue(K_SINK).getValue(); diff --git a/quarkus/addons/knative/eventing/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactoryTest.java b/quarkus/addons/knative/eventing/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactoryTest.java index 78cd2876025..120bfb650a3 100644 --- a/quarkus/addons/knative/eventing/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactoryTest.java +++ b/quarkus/addons/knative/eventing/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/eventing/KnativeEventingConfigSourceFactoryTest.java @@ -89,11 +89,12 @@ private static void assertProcessEvents(KnativeEventingConfigSource eventingConf assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-processinstances-events.connector", "quarkus-http"); assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-processinstances-events.url", DEFAULT_SINK_CONFIG); + assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-processdefinitions-events.connector", "quarkus-http"); + assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-processdefinitions-events.url", DEFAULT_SINK_CONFIG); + assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-usertaskinstances-events.connector", "quarkus-http"); assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-usertaskinstances-events.url", DEFAULT_SINK_CONFIG); - assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-variables-events.connector", "quarkus-http"); - assertContainsProperty(eventingConfigSource, "mp.messaging.outgoing.kogito-variables-events.url", DEFAULT_SINK_CONFIG); } private static void assertDefaultIncomingConnector(KnativeEventingConfigSource eventingConfigSource) { diff --git a/quarkus/addons/knative/serving/deployment/pom.xml b/quarkus/addons/knative/serving/deployment/pom.xml index 129e5bcf3c0..576dea893b0 100644 --- a/quarkus/addons/knative/serving/deployment/pom.xml +++ b/quarkus/addons/knative/serving/deployment/pom.xml @@ -53,6 +53,23 @@ org.kie.kogito kogito-serverless-workflow-rest-parser + + + + org.assertj + assertj-core + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + diff --git a/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/KogitoAddonKnativeServingProcessor.java b/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/KogitoAddonKnativeServingProcessor.java new file mode 100644 index 00000000000..f11134f5bd6 --- /dev/null +++ b/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/KogitoAddonKnativeServingProcessor.java @@ -0,0 +1,52 @@ +/* + * 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.addons.quarkus.knative.serving.deployment; + +import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.CloudEventKnativeParamsDecorator; +import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.PlainJsonKnativeParamsDecorator; +import org.kie.kogito.quarkus.addons.common.deployment.KogitoCapability; +import org.kie.kogito.quarkus.addons.common.deployment.OneOfCapabilityKogitoAddOnProcessor; + +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; + +public class KogitoAddonKnativeServingProcessor extends OneOfCapabilityKogitoAddOnProcessor { + + static final String FEATURE = "kogito-addons-quarkus-knative-serving"; + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } + + KogitoAddonKnativeServingProcessor() { + super(KogitoCapability.SERVERLESS_WORKFLOW); + } + + @BuildStep + public ReflectiveClassBuildItem reflectiveClasses() { + return new ReflectiveClassBuildItem(true, + true, + true, + CloudEventKnativeParamsDecorator.class, PlainJsonKnativeParamsDecorator.class); + } + +} diff --git a/quarkus/addons/knative/serving/deployment/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/KogitoAddonKnativeServingProcessorTest.java b/quarkus/addons/knative/serving/deployment/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/KogitoAddonKnativeServingProcessorTest.java new file mode 100644 index 00000000000..f76c2d3edd6 --- /dev/null +++ b/quarkus/addons/knative/serving/deployment/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/KogitoAddonKnativeServingProcessorTest.java @@ -0,0 +1,45 @@ +/* + * 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.addons.quarkus.knative.serving.deployment; + +import org.junit.jupiter.api.Test; +import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.CloudEventKnativeParamsDecorator; +import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.PlainJsonKnativeParamsDecorator; + +import static org.assertj.core.api.Assertions.assertThat; + +class KogitoAddonKnativeServingProcessorTest { + + private final KogitoAddonKnativeServingProcessor processor = new KogitoAddonKnativeServingProcessor(); + + @Test + void feature() { + assertThat(processor.feature()).isNotNull(); + assertThat(processor.feature().getName()).isEqualTo(KogitoAddonKnativeServingProcessor.FEATURE); + } + + @Test + void reflectiveClasses() { + assertThat(processor.reflectiveClasses()).isNotNull(); + assertThat(processor.reflectiveClasses().getClassNames()) + .containsExactlyInAnyOrder(CloudEventKnativeParamsDecorator.class.getName(), + PlainJsonKnativeParamsDecorator.class.getName()); + } +} diff --git a/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java b/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java index abcbda47995..b9f49ef000d 100644 --- a/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java +++ b/quarkus/addons/kubernetes/integration-tests/src/main/java/org/kie/kogito/addons/quarkus/kubernetes/Foo.java @@ -1,17 +1,20 @@ /* - * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * 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 * - * Licensed 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 * - * 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. + * 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.addons.quarkus.kubernetes; diff --git a/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java b/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java index c22bb072b11..bf1560edec3 100644 --- a/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java +++ b/quarkus/addons/kubernetes/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/kubernetes/ConfigValueExpanderIT.java @@ -1,17 +1,20 @@ /* - * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * 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 * - * Licensed 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 * - * 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. + * 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.addons.quarkus.kubernetes; diff --git a/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/DeadlineEventDeserializer.java b/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/DeadlineEventDeserializer.java index 0216fc5fade..660900af719 100644 --- a/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/DeadlineEventDeserializer.java +++ b/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/DeadlineEventDeserializer.java @@ -18,13 +18,13 @@ */ package org.kie.kogito.mail; -import org.kie.kogito.event.process.UserTaskDeadlineDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineDataEvent; import io.quarkus.kafka.client.serialization.ObjectMapperDeserializer; -public class DeadlineEventDeserializer extends ObjectMapperDeserializer { +public class DeadlineEventDeserializer extends ObjectMapperDeserializer { public DeadlineEventDeserializer() { - super(UserTaskDeadlineDataEvent.class); + super(UserTaskInstanceDeadlineDataEvent.class); } } diff --git a/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/QuarkusMailSender.java b/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/QuarkusMailSender.java index d03cc34f7c8..90af309c9a3 100644 --- a/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/QuarkusMailSender.java +++ b/quarkus/addons/mail/runtime/src/main/java/org/kie/kogito/mail/QuarkusMailSender.java @@ -24,7 +24,7 @@ import javax.inject.Inject; import org.eclipse.microprofile.reactive.messaging.Incoming; -import org.kie.kogito.event.process.UserTaskDeadlineDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineDataEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +39,7 @@ public class QuarkusMailSender { private ReactiveMailer mailer; @Incoming("kogito-deadline-consumer") - public void onDeadline(UserTaskDeadlineDataEvent event) { + public void onDeadline(UserTaskInstanceDeadlineDataEvent event) { MailInfo mailInfo = MailInfo.of(event.getData()); logger.info("Sending e-mail {}", mailInfo); Mail message = new Mail(); diff --git a/quarkus/addons/mail/runtime/src/test/java/org/kie/kogito/mail/QuarkusMailSenderTest.java b/quarkus/addons/mail/runtime/src/test/java/org/kie/kogito/mail/QuarkusMailSenderTest.java index 11240a14a7a..0489f1ed114 100644 --- a/quarkus/addons/mail/runtime/src/test/java/org/kie/kogito/mail/QuarkusMailSenderTest.java +++ b/quarkus/addons/mail/runtime/src/test/java/org/kie/kogito/mail/QuarkusMailSenderTest.java @@ -26,8 +26,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.UserTaskDeadlineDataEvent; -import org.kie.kogito.event.process.UserTaskDeadlineEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineEventBody; import io.quarkus.mailer.Mail; import io.quarkus.mailer.MockMailbox; @@ -61,8 +61,8 @@ void testMail() { notification.put(MailInfo.FROM_PROPERTY, "realbetisbalompie@gmail.com"); notification.put(MailInfo.TO_PROPERTY, TO + ",fulanito@doesnotexist.com"); - UserTaskDeadlineEventBody eventData = UserTaskDeadlineEventBody.create("1", notification).build(); - UserTaskDeadlineDataEvent event = new UserTaskDeadlineDataEvent(null, null, null, null, eventData, null, null, null, null); + UserTaskInstanceDeadlineEventBody eventData = UserTaskInstanceDeadlineEventBody.create().userTaskInstanceId("1").notification(notification).build(); + UserTaskInstanceDeadlineDataEvent event = new UserTaskInstanceDeadlineDataEvent(null, null, null, new HashMap<>(), eventData); sender.onDeadline(event); List messages = mailBox.getMessagesSentTo(TO); assertEquals(1, messages.size()); diff --git a/quarkus/addons/messaging/deployment/src/main/java/org/kie/kogito/addon/cloudevents/quarkus/deployment/KogitoAddOnMessagingProcessor.java b/quarkus/addons/messaging/deployment/src/main/java/org/kie/kogito/addon/cloudevents/quarkus/deployment/KogitoAddOnMessagingProcessor.java index f6b17ffd31f..ef95b1ffd02 100644 --- a/quarkus/addons/messaging/deployment/src/main/java/org/kie/kogito/addon/cloudevents/quarkus/deployment/KogitoAddOnMessagingProcessor.java +++ b/quarkus/addons/messaging/deployment/src/main/java/org/kie/kogito/addon/cloudevents/quarkus/deployment/KogitoAddOnMessagingProcessor.java @@ -31,7 +31,7 @@ import org.drools.codegen.common.GeneratedFileType; import org.jboss.jandex.DotName; import org.jbpm.compiler.canonical.ProcessMetaData; -import org.kie.kogito.addon.quarkus.messaging.common.message.CloudEventHttpOutgoingDecorator; +import org.kie.kogito.addon.quarkus.common.reactive.messaging.http.CloudEventHttpOutgoingDecorator; import org.kie.kogito.codegen.api.context.KogitoBuildContext; import org.kie.kogito.codegen.process.ProcessGenerator; import org.kie.kogito.quarkus.addons.common.deployment.AnyEngineKogitoAddOnProcessor; diff --git a/quarkus/addons/microprofile-config-service-catalog/deployment/pom.xml b/quarkus/addons/microprofile-config-service-catalog/deployment/pom.xml index 8bcc7de8d35..275247cafab 100644 --- a/quarkus/addons/microprofile-config-service-catalog/deployment/pom.xml +++ b/quarkus/addons/microprofile-config-service-catalog/deployment/pom.xml @@ -33,14 +33,17 @@ Kogito Add-On MicroProfile Config Service Catalog - Deployment + + io.quarkus + quarkus-arc-deployment + org.kie.kogito - kogito-addons-quarkus-microprofile-config-service-catalog - 2.0.0-SNAPSHOT + kogito-addons-quarkus-common-deployment - io.quarkus - quarkus-arc-deployment + org.kie.kogito + kogito-addons-quarkus-microprofile-config-service-catalog diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/HumanTaskDeadlineEvent.java b/quarkus/addons/microprofile-config-service-catalog/deployment/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalogProcessor.java similarity index 51% rename from api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/HumanTaskDeadlineEvent.java rename to quarkus/addons/microprofile-config-service-catalog/deployment/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalogProcessor.java index a07ce9648b0..7397c25dbf0 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/event/HumanTaskDeadlineEvent.java +++ b/quarkus/addons/microprofile-config-service-catalog/deployment/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalogProcessor.java @@ -16,43 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -package org.kie.kogito.internal.process.event; -import java.util.Map; +package org.kie.kogito.addons.quarkus.microprofile.config.service.catalog; -import org.kie.api.event.process.ProcessEvent; -import org.kie.kogito.process.workitem.HumanTaskWorkItem; +import org.kie.kogito.quarkus.addons.common.deployment.AnyEngineKogitoAddOnProcessor; -/** - * An event when a dealine for task has expired - */ -public interface HumanTaskDeadlineEvent - extends - ProcessEvent { +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; - enum DeadlineType { - Started, - Completed - } +public class MicroProfileConfigServiceCatalogProcessor extends AnyEngineKogitoAddOnProcessor { - /** - * Returns work item which timeout expires - * - * @return work item - */ - HumanTaskWorkItem getWorkItem(); + private static final String FEATURE = "kogito-addon-microprofile-config-service-catalog-extension"; - /** - * Returns notification data - * - * @return key-value pair list - */ - Map getNotification(); + @BuildStep + public FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } - /** - * Returns dealine type - * - * @return not started or not completed - */ - DeadlineType getType(); -} \ No newline at end of file +} diff --git a/quarkus/addons/microprofile-config-service-catalog/integration-tests/src/test/resources/application.properties b/quarkus/addons/microprofile-config-service-catalog/integration-tests/src/main/resources/application.properties similarity index 100% rename from quarkus/addons/microprofile-config-service-catalog/integration-tests/src/test/resources/application.properties rename to quarkus/addons/microprofile-config-service-catalog/integration-tests/src/main/resources/application.properties diff --git a/quarkus/addons/microprofile-config-service-catalog/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/it/MicroProfileConfigServiceAddonIT.java b/quarkus/addons/microprofile-config-service-catalog/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/it/MicroProfileConfigServiceAddonIT.java index 40ad0aa825f..5a4b5bc4d7d 100644 --- a/quarkus/addons/microprofile-config-service-catalog/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/it/MicroProfileConfigServiceAddonIT.java +++ b/quarkus/addons/microprofile-config-service-catalog/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/it/MicroProfileConfigServiceAddonIT.java @@ -23,13 +23,13 @@ import org.junit.jupiter.api.Test; import io.quarkus.test.common.QuarkusTestResource; -import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; -@QuarkusTest +@QuarkusIntegrationTest @QuarkusTestResource(ServiceMock.class) class MicroProfileConfigServiceAddonIT { diff --git a/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalog.java b/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalog.java index dcfd4eb51f0..362a3fcd16e 100644 --- a/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalog.java +++ b/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/java/org/kie/kogito/addons/quarkus/microprofile/config/service/catalog/MicroProfileConfigServiceCatalog.java @@ -22,9 +22,8 @@ import java.util.Optional; import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; import org.kie.kogito.addons.k8s.resource.catalog.KubernetesServiceCatalog; import org.kie.kogito.addons.k8s.resource.catalog.KubernetesServiceCatalogKey; @@ -33,13 +32,9 @@ public class MicroProfileConfigServiceCatalog implements KubernetesServiceCatalo private static final String CONFIG_PREFIX = "org.kie.kogito.addons.discovery."; - @Inject - Config config; - @Override public Optional getServiceAddress(KubernetesServiceCatalogKey key) { - - return config.getOptionalValue(CONFIG_PREFIX + key.getProtocol().getValue() + ":" + key.getCoordinates(), String.class) - .map(URI::create); + return ConfigProvider.getConfig() + .getOptionalValue(CONFIG_PREFIX + key.getProtocol().getValue() + ":" + key.getCoordinates(), String.class).map(URI::create); } } diff --git a/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/resources/META-INF/kogito.addon b/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/resources/META-INF/kogito.addon new file mode 100644 index 00000000000..b3acaabad74 --- /dev/null +++ b/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/resources/META-INF/kogito.addon @@ -0,0 +1 @@ +microprofile-config-service-catalog \ No newline at end of file diff --git a/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 00000000000..d3614598409 --- /dev/null +++ b/quarkus/addons/microprofile-config-service-catalog/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,30 @@ +# +# 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. +# + +name: Kogito Add-On Microprofile Config Service Catalog +description: Kogito Add-On to use the service discovery API at the time the resolved values can be configured as properties +metadata: + keywords: + - kogito + - kubernetes + - service + - discovery + guide: https://quarkus.io/version/2.13/guides/kogito + categories: + - "business-automation" diff --git a/quarkus/addons/pom.xml b/quarkus/addons/pom.xml index d438b034705..a78c5ea1188 100644 --- a/quarkus/addons/pom.xml +++ b/quarkus/addons/pom.xml @@ -105,7 +105,7 @@
maven-failsafe-plugin - ${version.failsafe.plugin} + ${version.maven-surefire} org.jboss.logmanager.LogManager diff --git a/quarkus/addons/python/integration-tests/pom.xml b/quarkus/addons/python/integration-tests/pom.xml index 480e6f6395c..64bfbb36317 100644 --- a/quarkus/addons/python/integration-tests/pom.xml +++ b/quarkus/addons/python/integration-tests/pom.xml @@ -145,6 +145,19 @@ native + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + ${env.JAVA_HOME}/lib/server + + + + + \ No newline at end of file diff --git a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/RestAnnotator.java b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java similarity index 64% rename from kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/RestAnnotator.java rename to quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java index be952e6cff3..73bdac8cc7f 100644 --- a/kogito-codegen-modules/kogito-codegen-api/src/main/java/org/kie/kogito/codegen/api/rest/RestAnnotator.java +++ b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java @@ -16,14 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -package org.kie.kogito.codegen.api.rest; +package org.kie.kogito.resource.exceptions; -import java.util.Optional; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; -import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; +import org.kie.kogito.process.workitem.WorkItemExecutionException; -public interface RestAnnotator { - > boolean isRestAnnotated(T node); +@Provider +public class WorkItemExecutionExceptionMapper extends BaseExceptionMapper { - > Optional getEndpointValue(T node); + @Override + public Response toResponse(WorkItemExecutionException exception) { + return exceptionsHandler.mapException(exception); + } } diff --git a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/pom.xml b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/pom.xml index c38a5dc4e1a..066b1d50075 100644 --- a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/pom.xml +++ b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/pom.xml @@ -48,7 +48,7 @@ org.drools - drools-drl-quarkus-util-deployment + drools-quarkus-util-deployment diff --git a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java index 07ff09b1149..74c5c39f45c 100644 --- a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java +++ b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoAssetsProcessor.java @@ -71,8 +71,8 @@ import io.quarkus.vertx.http.deployment.spi.AdditionalStaticResourceBuildItem; import static org.drools.codegen.common.GeneratedFileType.COMPILED_CLASS; -import static org.drools.drl.quarkus.util.deployment.DroolsQuarkusResourceUtils.compileGeneratedSources; -import static org.drools.drl.quarkus.util.deployment.DroolsQuarkusResourceUtils.makeBuildItems; +import static org.drools.quarkus.util.deployment.DroolsQuarkusResourceUtils.compileGeneratedSources; +import static org.drools.quarkus.util.deployment.DroolsQuarkusResourceUtils.makeBuildItems; import static org.kie.efesto.common.api.constants.Constants.INDEXFILE_DIRECTORY_PROPERTY; import static org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.HOT_RELOAD_SUPPORT_PATH; import static org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.dumpFilesToDisk; diff --git a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoQuarkusResourceUtils.java b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoQuarkusResourceUtils.java index d2911db74a6..3b10caeaa95 100644 --- a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoQuarkusResourceUtils.java +++ b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common-deployment/src/main/java/org/kie/kogito/quarkus/common/deployment/KogitoQuarkusResourceUtils.java @@ -34,7 +34,7 @@ import org.drools.codegen.common.DroolsModelBuildContext; import org.drools.codegen.common.GeneratedFile; import org.drools.codegen.common.GeneratedFileType; -import org.drools.drl.quarkus.util.deployment.QuarkusAppPaths; +import org.drools.quarkus.util.deployment.QuarkusAppPaths; import org.drools.util.PortablePath; import org.eclipse.microprofile.config.ConfigProvider; import org.jboss.jandex.CompositeIndex; diff --git a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common/src/main/java/org/kie/kogito/quarkus/registry/ProcessDefinitionRegistration.java b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common/src/main/java/org/kie/kogito/quarkus/registry/ProcessDefinitionRegistration.java new file mode 100644 index 00000000000..4ec977733a0 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common/src/main/java/org/kie/kogito/quarkus/registry/ProcessDefinitionRegistration.java @@ -0,0 +1,50 @@ +/* + * 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.quarkus.registry; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Instance; +import javax.inject.Inject; + +import org.kie.kogito.Application; +import org.kie.kogito.process.Processes; +import org.kie.kogito.quarkus.config.KogitoRuntimeConfig; +import org.kie.kogito.services.registry.ProcessDefinitionEventRegistry; + +import io.quarkus.runtime.StartupEvent; + +@ApplicationScoped +public class ProcessDefinitionRegistration { + + Instance processes; + ProcessDefinitionEventRegistry processDefinitionRegistry; + + @Inject + public ProcessDefinitionRegistration(Application application, KogitoRuntimeConfig runtimeConfig, Instance processes) { + this.processes = processes; + this.processDefinitionRegistry = new ProcessDefinitionEventRegistry(application, runtimeConfig.serviceUrl.orElse(null)); + } + + void onStartUp(@Observes StartupEvent startupEvent) { + if (processes.isResolvable()) { + processDefinitionRegistry.register(processes.get()); + } + } +} diff --git a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java index 4ff48680f9a..14819353e82 100644 --- a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java +++ b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java @@ -22,20 +22,29 @@ import org.kie.kogito.core.process.incubation.quarkus.support.QuarkusProcessIdFactory; import org.kie.kogito.core.process.incubation.quarkus.support.QuarkusStatefulProcessService; import org.kie.kogito.core.process.incubation.quarkus.support.QuarkusStraightThroughProcessService; -import org.kie.kogito.event.process.AttachmentEventBody; -import org.kie.kogito.event.process.CommentEventBody; -import org.kie.kogito.event.process.MilestoneEventBody; -import org.kie.kogito.event.process.NodeInstanceEventBody; -import org.kie.kogito.event.process.ProcessDataEvent; -import org.kie.kogito.event.process.ProcessErrorEventBody; -import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.UserTaskDeadlineDataEvent; -import org.kie.kogito.event.process.UserTaskDeadlineEventBody; -import org.kie.kogito.event.process.UserTaskInstanceDataEvent; -import org.kie.kogito.event.process.UserTaskInstanceEventBody; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceErrorDataEvent; +import org.kie.kogito.event.process.ProcessInstanceErrorEventBody; +import org.kie.kogito.event.process.ProcessInstanceNodeDataEvent; +import org.kie.kogito.event.process.ProcessInstanceNodeEventBody; +import org.kie.kogito.event.process.ProcessInstanceSLADataEvent; +import org.kie.kogito.event.process.ProcessInstanceSLAEventBody; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateEventBody; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; +import org.kie.kogito.event.process.ProcessInstanceVariableEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceAssignmentDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceAssignmentEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceAttachmentDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceAttachmentEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceCommentDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceCommentEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceStateEventBody; +import org.kie.kogito.event.usertask.UserTaskInstanceVariableDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceVariableEventBody; import org.kie.kogito.quarkus.workflow.KogitoBeanProducer; import org.kie.kogito.quarkus.workflow.deployment.WorkflowProcessor; @@ -58,20 +67,30 @@ public FeatureBuildItem featureBuildItem() { @BuildStep public ReflectiveClassBuildItem eventsApiReflection() { return new ReflectiveClassBuildItem(true, true, - AttachmentEventBody.class.getName(), - CommentEventBody.class.getName(), - MilestoneEventBody.class.getName(), - NodeInstanceEventBody.class.getName(), - ProcessDataEvent.class.getName(), - ProcessErrorEventBody.class.getName(), - ProcessInstanceDataEvent.class.getName(), - ProcessInstanceEventBody.class.getName(), - UserTaskDeadlineDataEvent.class.getName(), - UserTaskDeadlineEventBody.class.getName(), + ProcessInstanceErrorEventBody.class.getName(), + ProcessInstanceErrorDataEvent.class.getName(), + ProcessInstanceNodeEventBody.class.getName(), + ProcessInstanceNodeDataEvent.class.getName(), + ProcessInstanceSLAEventBody.class.getName(), + ProcessInstanceSLADataEvent.class.getName(), + ProcessInstanceStateEventBody.class.getName(), + ProcessInstanceStateDataEvent.class.getName(), + ProcessInstanceVariableEventBody.class.getName(), + ProcessInstanceVariableDataEvent.class.getName(), UserTaskInstanceDataEvent.class.getName(), - UserTaskInstanceEventBody.class.getName(), - VariableInstanceDataEvent.class.getName(), - VariableInstanceEventBody.class.getName()); + UserTaskInstanceAssignmentEventBody.class.getName(), + UserTaskInstanceAssignmentDataEvent.class.getName(), + UserTaskInstanceAttachmentEventBody.class.getName(), + UserTaskInstanceAttachmentDataEvent.class.getName(), + UserTaskInstanceCommentEventBody.class.getName(), + UserTaskInstanceCommentDataEvent.class.getName(), + UserTaskInstanceDeadlineEventBody.class.getName(), + UserTaskInstanceDeadlineDataEvent.class.getName(), + UserTaskInstanceStateEventBody.class.getName(), + UserTaskInstanceStateDataEvent.class.getName(), + UserTaskInstanceVariableEventBody.class.getName(), + UserTaskInstanceVariableDataEvent.class.getName()); + } @BuildStep diff --git a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-integration-test/src/main/java/org/acme/GreetingResource.java b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-integration-test/src/main/java/org/acme/GreetingResource.java index fd2456d61f2..608707a960c 100644 --- a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-integration-test/src/main/java/org/acme/GreetingResource.java +++ b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-integration-test/src/main/java/org/acme/GreetingResource.java @@ -55,8 +55,6 @@ public class GreetingResource { @POST public DataContext hello(Map payload) { // path: /processes/scripts - System.out.println(payload); - var id = appRoot.get(ProcessIds.class).get("scripts"); return svc.evaluate(id, MapDataContext.from(payload)); } diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/ClassAnnotatedWorkflowHandlerGenerator.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/ClassAnnotatedWorkflowHandlerGenerator.java index 32fce36910e..95d117f8859 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/ClassAnnotatedWorkflowHandlerGenerator.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/ClassAnnotatedWorkflowHandlerGenerator.java @@ -30,6 +30,7 @@ import org.kie.kogito.codegen.api.context.KogitoBuildContext; import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.type.ClassOrInterfaceType; import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType; import static com.github.javaparser.StaticJavaParser.parseType; @@ -46,16 +47,31 @@ public Collection generateHandlerClasses(KogitoBui protected abstract Stream generateHandler(KogitoBuildContext context, AnnotationInstance a); protected final com.github.javaparser.ast.type.Type fromClass(Type param) { + return fromClass(param, true); + } + + protected final com.github.javaparser.ast.type.Type fromClass(Type param, boolean includeGeneric) { switch (param.kind()) { case CLASS: - return parseClassOrInterfaceType(param.asClassType().name().toString()); + return parseClassOrInterfaceType(fromDotName(param.asClassType().name())); case PRIMITIVE: - return parseType(param.asPrimitiveType().name().toString()); + return parseType(fromDotName(param.asPrimitiveType().name())); case PARAMETERIZED_TYPE: - return parseClassOrInterfaceType(param.asParameterizedType().name().toString()) - .setTypeArguments(NodeList.nodeList(param.asParameterizedType().arguments().stream().map(this::fromClass).collect(Collectors.toList()))); + ClassOrInterfaceType result = parseClassOrInterfaceType(fromDotName(param.asParameterizedType().name())); + if (includeGeneric) { + result.setTypeArguments(NodeList.nodeList(param.asParameterizedType().arguments().stream().map(this::fromClass).collect(Collectors.toList()))); + } + return result; default: throw new UnsupportedOperationException("Kind " + param.kind() + " is not supported"); } } + + private String fromDotName(DotName dotName) { + String result = dotName.toString(); + if (dotName.isInner()) { + result = result.replace('$', '.'); + } + return result; + } } diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/ServerlessWorkflowAssetsProcessor.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/ServerlessWorkflowAssetsProcessor.java index 744fdfa12dc..2a3241b0ad2 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/ServerlessWorkflowAssetsProcessor.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/ServerlessWorkflowAssetsProcessor.java @@ -31,13 +31,16 @@ import org.kie.kogito.codegen.api.context.KogitoBuildContext; import org.kie.kogito.codegen.process.ProcessContainerGenerator; import org.kie.kogito.codegen.process.ProcessGenerator; -import org.kie.kogito.event.process.NodeInstanceEventBody; -import org.kie.kogito.event.process.ProcessDataEvent; -import org.kie.kogito.event.process.ProcessErrorEventBody; +import org.kie.kogito.event.process.NodeDefinition; +import org.kie.kogito.event.process.ProcessDefinitionDataEvent; +import org.kie.kogito.event.process.ProcessDefinitionEventBody; import org.kie.kogito.event.process.ProcessInstanceDataEvent; -import org.kie.kogito.event.process.ProcessInstanceEventBody; -import org.kie.kogito.event.process.VariableInstanceDataEvent; -import org.kie.kogito.event.process.VariableInstanceEventBody; +import org.kie.kogito.event.process.ProcessInstanceErrorEventBody; +import org.kie.kogito.event.process.ProcessInstanceNodeEventBody; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateEventBody; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; +import org.kie.kogito.event.process.ProcessInstanceVariableEventBody; import org.kie.kogito.process.expr.ExpressionHandler; import org.kie.kogito.quarkus.common.deployment.KogitoAddonsPreGeneratedSourcesBuildItem; import org.kie.kogito.quarkus.common.deployment.KogitoBuildContextBuildItem; @@ -118,13 +121,16 @@ void addOpenAPIModelSchema(List proces @BuildStep public ReflectiveClassBuildItem eventsApiReflection() { return new ReflectiveClassBuildItem(true, true, - NodeInstanceEventBody.class.getName(), - ProcessDataEvent.class.getName(), - ProcessErrorEventBody.class.getName(), + ProcessInstanceNodeEventBody.class.getName(), ProcessInstanceDataEvent.class.getName(), - ProcessInstanceEventBody.class.getName(), - VariableInstanceDataEvent.class.getName(), - VariableInstanceEventBody.class.getName()); + ProcessInstanceErrorEventBody.class.getName(), + ProcessInstanceStateDataEvent.class.getName(), + ProcessInstanceStateEventBody.class.getName(), + ProcessInstanceVariableDataEvent.class.getName(), + ProcessInstanceVariableEventBody.class.getName(), + ProcessDefinitionDataEvent.class.getName(), + ProcessDefinitionEventBody.class.getName(), + NodeDefinition.class.getName()); } @BuildStep diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/livereload/LiveReloadProcessor.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/livereload/LiveReloadProcessor.java index d58bb119c11..ba1fa4ba9bb 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/livereload/LiveReloadProcessor.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/deployment/livereload/LiveReloadProcessor.java @@ -34,7 +34,7 @@ import org.drools.codegen.common.GeneratedFile; import org.drools.codegen.common.GeneratedFileType; -import org.drools.drl.quarkus.util.deployment.DroolsQuarkusResourceUtils; +import org.drools.quarkus.util.deployment.DroolsQuarkusResourceUtils; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.jboss.jandex.IndexView; diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/openapi/WorkflowOpenApiHandlerGenerator.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/openapi/WorkflowOpenApiHandlerGenerator.java index 36c97d8d732..f502b34a834 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/openapi/WorkflowOpenApiHandlerGenerator.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-deployment/src/main/java/org/kie/kogito/quarkus/serverless/workflow/openapi/WorkflowOpenApiHandlerGenerator.java @@ -109,7 +109,7 @@ private WorkflowHandlerGeneratedFile generateHandler(KogitoBuildContext context, if (annotation != null) { methodCallExpr.addArgument(new CastExpr(fromClass(param), new MethodCallExpr(parameters, "remove").addArgument(new StringLiteralExpr(annotation.value().asString())))); } else { - methodCallExpr.addArgument(new MethodCallExpr("buildBody").addArgument(parameters).addArgument(new ClassExpr(fromClass(param)))); + methodCallExpr.addArgument(new MethodCallExpr("buildBody").addArgument(parameters).addArgument(new ClassExpr(fromClass(param, false)))); } } clazz.addMethod("getRestClass", Keyword.PROTECTED).setType(parseClassOrInterfaceType(Class.class.getCanonicalName()).setTypeArguments(classNameType)) diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-image-integration-test/src/main/resources/application.properties b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-image-integration-test/src/main/resources/application.properties index 4ff6404ec14..fa8c3221b0d 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-image-integration-test/src/main/resources/application.properties +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-image-integration-test/src/main/resources/application.properties @@ -17,7 +17,7 @@ # under the License. # -my_name=kogito +expression.my_name=kogito quarkus.container-image.build=true quarkus.devservices.enabled=false \ No newline at end of file diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/pom.xml b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/pom.xml index 49a2036d6d0..747039445b0 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/pom.xml +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/pom.xml @@ -63,6 +63,10 @@ io.quarkus quarkus-elytron-security-properties-file + + org.kie.kogito + kogito-addons-quarkus-process-management + org.kie.kogito @@ -150,6 +154,19 @@ + + org.kie.kogito + kogito-addons-quarkus-process-management-deployment + ${project.version} + pom + test + + + * + * + + + org.kie.kogito kogito-serverless-workflow-builder diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties index 464e0b8e6ea..ba20b794de0 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/application.properties @@ -9,7 +9,8 @@ quarkus.flyway.clean-at-start=true quarkus.http.test-port=0 quarkus.log.level=INFO -#quarkus.log.category."org.kie.kogito".level=DEBUG +quarkus.log.category."org.kie.kogito.testcontainers".level=WARN +quarkus.log.category."org.apache.kafka".level=WARN # To include the greethidden workflow kogito.codegen.ignoreHiddenFiles=false @@ -20,6 +21,7 @@ quarkus.kubernetes-client.devservices.enabled=false # OpenApi client properties, see OperationsMockService, which is mocking these two services quarkus.rest-client.multiplication.url=${multiplication-service-mock.url} quarkus.rest-client.subtraction.url=${subtraction-service-mock.url} +quarkus.rest-client.array_yaml.url=${array-service-mock.url} # OpenApi client properties to access the general purpose external-service, which is mocked by the ExternalServiceMock quarkus.rest-client.external_service_yaml.url=${external-service-mock.url} @@ -67,7 +69,7 @@ mp.messaging.incoming.event2Exclusive.path=/event2Exclusive mp.messaging.incoming.event3Exclusive.connector=quarkus-http mp.messaging.incoming.event3Exclusive.path=/event3Exclusive -my_name=javierito +expression.my_name=javierito # Kafka configuration for the sw tests that produce events mp.messaging.outgoing.kogito_outgoing_stream.connector=smallrye-kafka @@ -207,6 +209,12 @@ mp.messaging.outgoing.kogito-variables-events.value.serializer=org.apache.kafka. mp.messaging.outgoing.kogito-variables-events.group.id=kogito-data-index-it mp.messaging.outgoing.kogito-variables-events.auto.offset.reset=latest +mp.messaging.outgoing.kogito-processdefinitions-events.connector=smallrye-kafka +mp.messaging.outgoing.kogito-processdefinitions-events.topic=kogito-processdefinitions-events +mp.messaging.outgoing.kogito-processdefinitions-events.value.serializer=org.apache.kafka.common.serialization.StringSerializer +mp.messaging.outgoing.kogito-processdefinitions-events.group.id=kogito-data-index-it +mp.messaging.outgoing.kogito-processdefinitions-events.auto.offset.reset=latest + quarkus.native.additional-build-args=-H:SerializationConfigurationResources=serialization-config.json # Maximum Java heap to be used during the native image generation quarkus.native.native-image-xmx=8g diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/callback-state-with-timeouts-error-handler.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/callback-state-with-timeouts-error-handler.sw.json new file mode 100644 index 00000000000..eb5508c0ff5 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/callback-state-with-timeouts-error-handler.sw.json @@ -0,0 +1,135 @@ +{ + "id": "callback_state_with_timeouts_error_handler", + "version": "1.0", + "name": "Callback State With Timeouts Error Handler", + "expressionLang": "jsonpath", + "description": "Callback State With Timeouts Error Handler Test", + "start": "CallbackState", + "constants": {"duration":"PT5S"}, + "events": [ + { + "name": "callbackEvent", + "source": "", + "type": "callback_state_timeouts_event_type" + } + ], + "errors": [ + { + "name": "callbackError", + "code": "java.lang.Exception" + }, + { + "name": "timeoutError", + "code": "TimedOut" + } + ], + "functions": [ + { + "name": "callbackFunction", + "type": "rest", + "operation": "classpath:specs/external-service.yaml#sendRequest" + }, + { + "name": "publishSuccess", + "type": "asyncapi", + "operation": "specs/callbackResults.yaml#sendSuccess" + }, + { + "name": "publishTimeoutExpired", + "type": "asyncapi", + "operation": "specs/callbackResults.yaml#sendTimeoutExpired" + }, + { + "name": "publishFailure", + "type": "asyncapi", + "operation": "specs/callbackResults.yaml#sendFailed" + } + ], + "states": [ + { + "name": "CallbackState", + "type": "callback", + "action": { + "name": "callbackAction", + "functionRef": { + "refName": "callbackFunction", + "arguments": { + "query": "$.query" + } + } + }, + "eventRef": "callbackEvent", + "transition": "PublishSuccess", + "onErrors": [ + { + "errorRef": "callbackError", + "transition": "PublishError" + }, + { + "errorRef": "timeoutError", + "transition": "PublishTimeout" + } + ], + "timeouts": { + "eventTimeout": "$CONST.duration" + } + }, + { + "name": "PublishSuccess", + "type": "operation", + "actions": [ + { + "name": "publishSuccess", + "functionRef": "publishSuccess" + } + ], + "transition": "FinalizeSuccessful" + }, + { + "name": "FinalizeSuccessful", + "type": "inject", + "data": { + "lastExecutedState": "FinalizeSuccessful" + }, + "end": true + }, + { + "name": "PublishTimeout", + "type": "operation", + "actions": [ + { + "name": "publishTimeoutExpired", + "functionRef": "publishTimeoutExpired" + } + ], + "transition": "FinalizeTimeout" + }, + { + "name": "FinalizeTimeout", + "type": "inject", + "data": { + "lastExecutedState": "FinalizeTimeout" + }, + "end": true + }, + { + "name": "PublishError", + "type": "operation", + "actions": [ + { + "name": "publishFailure", + "functionRef": "publishFailure" + } + ], + "transition": "FinalizeWithError" + }, + { + "name": "FinalizeWithError", + "type": "inject", + "data": { + "lastExecutedState": "FinalizeWithError" + }, + "end": true + } + ] +} \ No newline at end of file diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/eventWithError.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/eventWithError.sw.json new file mode 100644 index 00000000000..b9e84b6d972 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/eventWithError.sw.json @@ -0,0 +1,95 @@ +{ + "id": "eventTimedout", + "version": "1.0", + "expressionLang": "jsonpath", + "name": "Workflow event test", + "description": "An test of a non starting event with timeout error", + "start": "printWaitMessage", + "events": [ + { + "name": "moveEvent", + "source": "", + "type": "move" + } + ], + "errors": [ + { + "name": "timeoutError", + "code": "TimedOut" + } + ], + "functions": [ + { + "name": "printMessage", + "type": "custom", + "operation": "sysout" + }, + { + "name": "publishTimeoutExpired", + "type": "asyncapi", + "operation": "specs/callbackResults.yaml#sendTimeoutExpired" + } + ] + , + "states": [ + { + "name": "printWaitMessage", + "type": "operation", + "actions": [ + { + "name": "printBeforeEvent", + "functionRef": { + "refName": "printMessage", + "arguments": { + "message": "$[*]" + } + } + } + ], + "transition": "waitForEvent" + }, + { + "name": "waitForEvent", + "type": "event", + "onEvents": [ + { + "eventRefs": [ + "moveEvent" + ], + "actions": [ + { + "name": "printAfterEvent", + "functionRef": { + "refName": "printMessage", + "arguments": { + "message": "$[*]" + } + } + } + ] + } + ], + "onErrors": [ + { + "errorRef": "timeoutError", + "transition": "PublishTimeout" + } + ], + "timeouts": { + "eventTimeout": "PT5S" + }, + "end":true + }, + { + "name": "PublishTimeout", + "type": "operation", + "actions": [ + { + "name": "publishTimeoutExpired", + "functionRef": "publishTimeoutExpired" + } + ], + "end": "true" + } + ] +} \ No newline at end of file diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json index b738e603ea6..9a0b96344ea 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/expression.sw.json @@ -29,7 +29,7 @@ { "name": "secretMessage", "type": "expression", - "operation": ".message |= \"my name is \"+$SECRET.my_name" + "operation": ".message |= \"my name is \"+$SECRET.expression.my_name" }, { "name": "constantMessage", diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/openapiarray.sw.json b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/openapiarray.sw.json new file mode 100644 index 00000000000..32645efec4f --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/openapiarray.sw.json @@ -0,0 +1,27 @@ +{ + "id": "openapiarray", + "name": "Open API Array Test", + "version": "v1.0", + "start": "DoIt", + "functions": [ + { + "name": "testArray", + "operation": "specs/array.yaml#testArray" + } + ], + "states": [ + { + "name": "DoIt", + "type": "operation", + "actions": [ + { + "name": "testArray", + "functionRef": { + "refName": "testArray", + "arguments": ".inputArray" + } + }], + "end": true + } + ] +} \ No newline at end of file diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/specs/array.yaml b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/specs/array.yaml new file mode 100644 index 00000000000..14fe0ad7746 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/specs/array.yaml @@ -0,0 +1,25 @@ +--- +openapi: 3.0.3 +info: + title: Generated API + version: "1.0" +paths: + /testArray: + post: + operationId: testArray + requestBody: + content: + application/json: + schema: + type: array + items: + type: number + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: + type: number diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/specs/callbackResults.yaml b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/specs/callbackResults.yaml new file mode 100644 index 00000000000..d5b962c7c76 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/main/resources/specs/callbackResults.yaml @@ -0,0 +1,49 @@ +asyncapi: '2.0.0' +id: 'callbackResults' +info: + title: Kafka Application + version: '1.0.0' + description: Kafka Application + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 +servers: + production: + url: localhost:9092 + description: Development server + protocol: kafka + protocolVersion: '1.0.0' +channels: + success: + description: A message channel for successful completions + publish: + operationId: sendSuccess + summary: Success + message: + $ref: '#/components/messages/message' + timeout: + description: A message channel for expired timeouts + publish: + operationId: sendTimeoutExpired + summary: Timeout Expired + message: + $ref: '#/components/messages/message' + error: + description: A message channel for failed executions + publish: + operationId: sendFailed + summary: Failed + message: + $ref: '#/components/messages/message' +components: + messages: + message: + name: message + title: A message + summary: A message + contentType: application/json + payload: + $ref: "#/components/schemas/message" + schemas: + message: + type: object diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/AbstractCallbackStateIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/AbstractCallbackStateIT.java index 56d2b254201..9b753f9566f 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/AbstractCallbackStateIT.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/AbstractCallbackStateIT.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; import org.kie.kogito.test.quarkus.QuarkusTestProperty; import org.kie.kogito.test.quarkus.kafka.KafkaTestClient; import org.kie.kogito.testcontainers.quarkus.KafkaQuarkusTestResource; @@ -72,7 +73,7 @@ void cleanUp() { } } - void executeCallbackStateSuccessfulPath(String callbackProcessPostUrl, + String executeCallbackStateSuccessfulPath(String callbackProcessPostUrl, String callbackProcessGetByIdUrl, String answer, String callbackEventType, @@ -81,9 +82,9 @@ void executeCallbackStateSuccessfulPath(String callbackProcessPostUrl, String processInput = buildProcessInput(SUCCESSFUL_QUERY); String processInstanceId = newProcessInstanceAndGetId(callbackProcessPostUrl, processInput); - JsonPath processInstanceEventContent = waitForKogitoProcessInstanceEvent(kafkaClient, true); - Map workflowDataMap = processInstanceEventContent.getMap("data.variables.workflowdata"); - assertThat(workflowDataMap).hasSize(1); + JsonPath processInstanceEventContent = + waitForKogitoProcessInstanceEvent(kafkaClient, ProcessInstanceVariableDataEvent.class, e -> "workflowdata".equals(e.get("data.variableName")), true); + Map workflowDataMap = processInstanceEventContent.getMap("data.variableValue"); assertThat(workflowDataMap).containsEntry("query", SUCCESSFUL_QUERY); // double check that the process instance is there. @@ -103,26 +104,29 @@ void executeCallbackStateSuccessfulPath(String callbackProcessPostUrl, // give some time for the event to be processed and the process to finish. assertProcessInstanceHasFinished(callbackProcessGetByIdUrl, processInstanceId, 1, 180); + return processInstanceId; } - void executeCallbackStateWithErrorPath(String callbackProcessPostUrl, String callbackProcessGetByIdUrl) throws Exception { + String executeCallbackStateWithErrorPath(String callbackProcessPostUrl, String callbackProcessGetByIdUrl) throws Exception { // start a new process instance and collect the results. String processInput = buildProcessInput(GENERATE_ERROR_QUERY); JsonPath result = newProcessInstance(callbackProcessPostUrl, processInput); String processInstanceId = result.get("id"); // ensure the process has failed as expected since GENERATE_ERROR_QUERY was used. + String lastExecutedState = result.getString("workflowdata.lastExecutedState"); assertThat(lastExecutedState).isEqualTo("FinalizeWithError"); - JsonPath processInstanceEventContent = waitForKogitoProcessInstanceEvent(kafkaClient, true); - Map workflowDataMap = processInstanceEventContent.getMap("data.variables.workflowdata"); - assertThat(workflowDataMap) - .hasSize(2) - .containsEntry("query", GENERATE_ERROR_QUERY) - .containsEntry("lastExecutedState", "FinalizeWithError"); + JsonPath variableLastExecutedStateEventContent = + waitForKogitoProcessInstanceEvent(kafkaClient, ProcessInstanceVariableDataEvent.class, e -> "workflowdata".equals(e.get("data.variableName")), true); + Map lastExecutedStateDataMap = variableLastExecutedStateEventContent.getMap("data.variableValue"); + + assertThat(lastExecutedStateDataMap).containsEntry("lastExecutedState", "FinalizeWithError"); + assertThat(lastExecutedStateDataMap).containsEntry("query", GENERATE_ERROR_QUERY); // the process instance should not be there since an end state was reached. assertProcessInstanceNotExists(callbackProcessGetByIdUrl, processInstanceId); + return processInstanceId; } protected static String buildProcessInput(String query) { diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CallbackStateWithTimeoutsErrorHandlerIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CallbackStateWithTimeoutsErrorHandlerIT.java new file mode 100644 index 00000000000..0c166769adb --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/CallbackStateWithTimeoutsErrorHandlerIT.java @@ -0,0 +1,100 @@ +/* + * 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.quarkus.workflows; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; +import org.kie.kogito.event.Converter; +import org.kie.kogito.event.cloudevents.CloudEventExtensionConstants; +import org.kie.kogito.event.impl.StringCloudEventUnmarshallerFactory; +import org.kie.kogito.testcontainers.quarkus.KafkaQuarkusTestResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.cloudevents.CloudEvent; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.kie.kogito.quarkus.workflows.ExternalServiceMock.SUCCESSFUL_QUERY; +import static org.kie.kogito.test.utils.ProcessInstancesRESTTestUtils.assertProcessInstanceExists; +import static org.kie.kogito.test.utils.ProcessInstancesRESTTestUtils.assertProcessInstanceHasFinished; +import static org.kie.kogito.test.utils.ProcessInstancesRESTTestUtils.newProcessInstanceAndGetId; + +@QuarkusIntegrationTest +@QuarkusTestResource(ExternalServiceMock.class) +@QuarkusTestResource(KafkaQuarkusTestResource.class) +class CallbackStateWithTimeoutsErrorHandlerIT extends AbstractCallbackStateIT { + private static final Logger LOGGER = LoggerFactory.getLogger(CallbackStateWithTimeoutsErrorHandlerIT.class); + + private static final String CALLBACK_STATE_TIMEOUTS_SERVICE_URL = "/callback_state_with_timeouts_error_handler"; + private static final String CALLBACK_STATE_TIMEOUTS_GET_BY_ID_URL = CALLBACK_STATE_TIMEOUTS_SERVICE_URL + "/{id}"; + private static final String CALLBACK_STATE_TIMEOUTS_EVENT_TYPE = "callback_state_timeouts_event_type"; + private static final String CALLBACK_STATE_TIMEOUTS_TOPIC = "callback_state_timeouts_event_type"; + + @Test + @SuppressWarnings("squid:S2699") + void callbackStateTimeoutsSuccessful() throws Exception { + String processInstanceId = executeCallbackStateSuccessfulPath(CALLBACK_STATE_TIMEOUTS_SERVICE_URL, + CALLBACK_STATE_TIMEOUTS_GET_BY_ID_URL, + ANSWER, + CALLBACK_STATE_TIMEOUTS_EVENT_TYPE, + CALLBACK_STATE_TIMEOUTS_TOPIC); + waitForFinalizedEvent(processInstanceId, "success"); + } + + @Test + void callbackStateTimeoutsExceeded() throws Exception { + String processInput = buildProcessInput(SUCCESSFUL_QUERY); + String processInstanceId = newProcessInstanceAndGetId(CALLBACK_STATE_TIMEOUTS_SERVICE_URL, processInput); + assertProcessInstanceExists(CALLBACK_STATE_TIMEOUTS_GET_BY_ID_URL, processInstanceId); + + assertProcessInstanceHasFinished(CALLBACK_STATE_TIMEOUTS_GET_BY_ID_URL, processInstanceId, 1, 10); + waitForFinalizedEvent(processInstanceId, "timeout"); + } + + @Test + @SuppressWarnings("squid:S2699") + void callbackStateWithError() throws Exception { + String processInstanceId = executeCallbackStateWithErrorPath(CALLBACK_STATE_TIMEOUTS_SERVICE_URL, CALLBACK_STATE_TIMEOUTS_GET_BY_ID_URL); + waitForFinalizedEvent(processInstanceId, "error"); + } + + private void waitForFinalizedEvent(String processInstanceId, String topic) throws InterruptedException { + Converter converter = new StringCloudEventUnmarshallerFactory(objectMapper).unmarshaller(Map.class).cloudEvent(); + final CountDownLatch countDownLatch = new CountDownLatch(1); + kafkaClient.consume(topic, v -> { + try { + CloudEvent event = converter.convert(v); + LOGGER.debug("Found on topic {} CE {}", topic, event); + if (processInstanceId.equals(event.getExtension(CloudEventExtensionConstants.PROCESS_INSTANCE_ID))) { + countDownLatch.countDown(); + } + } catch (IOException e) { + LOGGER.info("Unmarshall exception", e); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + assertThat(countDownLatch.getCount()).isZero(); + } +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/EventTimedoutIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/EventTimedoutIT.java new file mode 100644 index 00000000000..292fbcab110 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/EventTimedoutIT.java @@ -0,0 +1,96 @@ +/* + * 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.quarkus.workflows; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.kafka.common.serialization.ByteArrayDeserializer; +import org.apache.kafka.common.serialization.ByteArraySerializer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.kie.kogito.event.Converter; +import org.kie.kogito.event.cloudevents.CloudEventExtensionConstants; +import org.kie.kogito.event.impl.ByteArrayCloudEventUnmarshallerFactory; +import org.kie.kogito.test.quarkus.QuarkusTestProperty; +import org.kie.kogito.test.quarkus.kafka.KafkaTypedTestClient; +import org.kie.kogito.testcontainers.quarkus.KafkaQuarkusTestResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import io.cloudevents.CloudEvent; +import io.cloudevents.jackson.JsonFormat; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.kie.kogito.quarkus.workflows.AssuredTestUtils.startProcess; + +@QuarkusIntegrationTest +@QuarkusTestResource(KafkaQuarkusTestResource.class) +public class EventTimedoutIT { + + private final static Logger logger = LoggerFactory.getLogger(EventTimedoutIT.class); + + @QuarkusTestProperty(name = KafkaQuarkusTestResource.KOGITO_KAFKA_PROPERTY) + String kafkaBootstrapServers; + private ObjectMapper objectMapper; + private KafkaTypedTestClient kafkaClient; + + @BeforeEach + void setup() { + kafkaClient = new KafkaTypedTestClient<>(kafkaBootstrapServers, ByteArraySerializer.class, ByteArrayDeserializer.class); + objectMapper = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .registerModule(JsonFormat.getCloudEventJacksonModule()) + .disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + } + + @AfterEach + void cleanUp() { + if (kafkaClient != null) { + kafkaClient.shutdown(); + } + } + + @Test + void testTimedout() throws InterruptedException { + String id = startProcess("eventTimedout"); + Converter converter = new ByteArrayCloudEventUnmarshallerFactory(objectMapper).unmarshaller(Map.class).cloudEvent(); + final CountDownLatch countDownLatch = new CountDownLatch(1); + kafkaClient.consume("timeout", v -> { + try { + CloudEvent event = converter.convert(v); + if (id.equals(event.getExtension(CloudEventExtensionConstants.PROCESS_INSTANCE_ID))) { + countDownLatch.countDown(); + } + } catch (IOException e) { + logger.info("Unmarshall exception", e); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + assertThat(countDownLatch.getCount()).isZero(); + } +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/OpenAPIArrayFlowIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/OpenAPIArrayFlowIT.java new file mode 100644 index 00000000000..c4923c191bb --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/OpenAPIArrayFlowIT.java @@ -0,0 +1,57 @@ +/* + * 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.quarkus.workflows; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; + +@QuarkusTestResource(OpenAPIArrayMockService.class) +@QuarkusIntegrationTest +class OpenAPIArrayFlowIT { + + @BeforeAll + static void init() { + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + } + + @Test + void testArray() { + given() + .contentType(ContentType.JSON) + .when() + .body(Collections.singletonMap("inputArray", Arrays.asList(1, 2, 3, 4))) + .post("/openapiarray") + .then() + .statusCode(201) + .body("id", notNullValue()) + .body("workflowdata.response", is(Arrays.asList(1, 2, 3, 4))); + } +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/OpenAPIArrayMockService.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/OpenAPIArrayMockService.java new file mode 100644 index 00000000000..c67a911d8e3 --- /dev/null +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/OpenAPIArrayMockService.java @@ -0,0 +1,62 @@ +/* + * 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.quarkus.workflows; + +import java.util.Map; +import java.util.function.UnaryOperator; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.MappingBuilder; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; + +public class OpenAPIArrayMockService implements QuarkusTestResourceLifecycleManager { + + private static WireMockServer arrayService; + + @Override + public Map start() { + arrayService = startServer("[1,2,3,4]", p -> p); + return Map.of("array-service-mock.url", arrayService.baseUrl()); + } + + @Override + public void stop() { + if (arrayService != null) { + arrayService.stop(); + } + } + + private static WireMockServer startServer(final String response, UnaryOperator function) { + final WireMockServer server = new WireMockServer(options().dynamicPort()); + server.start(); + server.stubFor(function.apply(post(urlEqualTo("/testArray")).withRequestBody(equalToJson("[1,2,3,4]"))) + .withPort(server.port()) + .willReturn(aResponse() + .withHeader("Content-Type", "application/json") + .withBody(response))); + return server; + } +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/PojoServiceIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/PojoServiceIT.java index 737e53e19bb..728b7c20122 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/PojoServiceIT.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/PojoServiceIT.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.kie.kogito.event.process.ProcessInstanceVariableDataEvent; import org.kie.kogito.test.quarkus.QuarkusTestProperty; import org.kie.kogito.test.quarkus.kafka.KafkaTestClient; import org.kie.kogito.testcontainers.quarkus.KafkaQuarkusTestResource; @@ -132,8 +133,9 @@ void testTypesPojo() throws Exception { .body("workflowdata.enabled", is(enabled)) .body("workflowdata.birthDate", is(birthDate.getTime())); - JsonPath processInstanceEventContent = waitForKogitoProcessInstanceEvent(kafkaClient, true); - Map workflowDataMap = processInstanceEventContent.getMap("data.variables.workflowdata"); + JsonPath processInstanceEventContent = waitForKogitoProcessInstanceEvent(kafkaClient, ProcessInstanceVariableDataEvent.class, + e -> "pojoServiceTypes".equals(e.get("kogitoprocid")) && "workflowdata".equals(e.get("data.variableName")), true); + Map workflowDataMap = processInstanceEventContent.getMap("data.variableValue"); assertThat(workflowDataMap) .hasSize(9) .containsEntry("name", "javieritoPerson") @@ -161,8 +163,9 @@ private void doIt(String flowName) throws Exception { .body("id", notNullValue()) .body("workflowdata.name", is("javieritoPerson")) .body("workflowdata.age", nullValue()); - JsonPath processInstanceEventContent = waitForKogitoProcessInstanceEvent(kafkaClient, true); - Map workflowDataMap = processInstanceEventContent.getMap("data.variables.workflowdata"); + JsonPath processInstanceEventContent = waitForKogitoProcessInstanceEvent(kafkaClient, ProcessInstanceVariableDataEvent.class, + e -> flowName.equals(e.get("kogitoprocid")) && "workflowdata".equals(e.get("data.variableName")), true); + Map workflowDataMap = processInstanceEventContent.getMap("data.variableValue"); assertThat(workflowDataMap).hasSize(1); assertThat(workflowDataMap).containsEntry("name", "javieritoPerson"); } diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowEventIT.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowEventIT.java index 85bb0815f7d..a21b62e08ee 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowEventIT.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowEventIT.java @@ -18,20 +18,29 @@ */ package org.kie.kogito.quarkus.workflows; +import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.ProcessDataEvent; +import org.kie.kogito.event.EventPublisher; +import org.kie.kogito.event.process.ProcessDefinitionDataEvent; +import org.kie.kogito.event.process.ProcessDefinitionEventBody; +import org.kie.kogito.event.process.ProcessInstanceDataEvent; import org.kie.kogito.test.quarkus.QuarkusTestProperty; import org.kie.kogito.test.quarkus.kafka.KafkaTestClient; import org.kie.kogito.testcontainers.quarkus.KafkaQuarkusTestResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.shaded.org.awaitility.Awaitility; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -42,6 +51,7 @@ import io.restassured.http.ContentType; import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -54,7 +64,6 @@ public class WorkflowEventIT { } private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowEventIT.class); - public static final String KOGITO_PROCESSINSTANCES_EVENTS = "kogito-processinstances-events"; public KafkaTestClient kafkaClient; private ObjectMapper mapper; @@ -77,16 +86,16 @@ void testWorkflowEvents() throws Exception { String username = "buddy"; String password = "buddy"; - kafkaClient.consume(Set.of(KOGITO_PROCESSINSTANCES_EVENTS), s -> { + kafkaClient.consume(Set.of(EventPublisher.PROCESS_INSTANCES_TOPIC_NAME), s -> { LOGGER.info("Received from kafka: {}", s); try { - ProcessDataEvent event = mapper.readValue(s, ProcessDataEvent.class); + ProcessInstanceDataEvent event = mapper.readValue(s, ProcessInstanceDataEvent.class); Map data = (Map) event.getData(); if ("secure".equals(data.get("processId"))) { - if (event.getType().equals("ProcessInstanceEvent")) { - assertEquals("ProcessInstanceEvent", event.getType()); + if (event.getType().equals("ProcessInstanceStateDataEvent")) { + assertEquals("ProcessInstanceStateEvent", event.getType()); assertEquals("/secure", event.getSource().toString()); - assertEquals("secure", data.get("processId")); + assertEquals("secure", event.getKogitoProcessId()); assertEquals("1.0", event.getKogitoProcessInstanceVersion()); assertEquals(username, event.getKogitoIdentity()); } @@ -109,4 +118,37 @@ void testWorkflowEvents() throws Exception { future.get(10, TimeUnit.SECONDS); } -} \ No newline at end of file + + @Test + void testWorkflowDefinitionsEvents() { + Collection definitionDataEvents = new ConcurrentLinkedQueue<>(); + kafkaClient.consume(Set.of(EventPublisher.PROCESS_DEFINITIONS_TOPIC_NAME), s -> { + LOGGER.debug("Received from kafka: {}", s); + try { + ProcessDefinitionDataEvent event = mapper.readValue(s, ProcessDefinitionDataEvent.class); + definitionDataEvents.add(event); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + }); + + List processIds = given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .when() + .get("/management/processes") + .then() + .statusCode(200) + .extract() + .body().as(List.class); + + Awaitility.waitAtMost(10, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).untilAsserted(() -> assertThat(definitionDataEvents).hasSize(processIds.size())); + + List processIdsFromEvent = definitionDataEvents.stream() + .map(ProcessDefinitionDataEvent::getData) + .map(ProcessDefinitionEventBody::getId) + .collect(Collectors.toList()); + + assertThat(processIdsFromEvent).containsAll(processIds); + } +} diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowTestUtils.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowTestUtils.java index b3443912543..7a381b0089f 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowTestUtils.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow-integration-test/src/test/java/org/kie/kogito/quarkus/workflows/WorkflowTestUtils.java @@ -21,15 +21,20 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; +import org.kie.kogito.event.DataEvent; +import org.kie.kogito.event.process.ProcessInstanceStateDataEvent; import org.kie.kogito.test.quarkus.kafka.KafkaTestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.restassured.path.json.JsonPath; import static org.assertj.core.api.Assertions.assertThat; public class WorkflowTestUtils { - + private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowTestUtils.class); public static final int TIME_OUT_SECONDS = 50; public static final String KOGITO_PROCESSINSTANCES_EVENTS = "kogito-processinstances-events"; @@ -37,19 +42,31 @@ private WorkflowTestUtils() { } public static JsonPath waitForKogitoProcessInstanceEvent(KafkaTestClient kafkaClient, boolean shutdownAfterConsume) throws Exception { + return waitForKogitoProcessInstanceEvent(kafkaClient, ProcessInstanceStateDataEvent.class, (e) -> true, shutdownAfterConsume); + } + + public static > JsonPath waitForKogitoProcessInstanceEvent(KafkaTestClient kafkaClient, Class eventType, Predicate predicate, boolean shutdownAfterConsume) + throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); - final AtomicReference cloudEvent = new AtomicReference<>(); + final AtomicReference cloudEvent = new AtomicReference<>(); kafkaClient.consume(KOGITO_PROCESSINSTANCES_EVENTS, rawCloudEvent -> { - cloudEvent.set(rawCloudEvent); - countDownLatch.countDown(); + JsonPath path = new JsonPath(rawCloudEvent); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("CLOUD EVENT: {}", path.prettyPrint()); + } + String type = path.get("type"); + if (eventType.getSimpleName().equals(type) && predicate.test(path)) { + cloudEvent.set(path); + countDownLatch.countDown(); + } }); // give some time to consume the event assertThat(countDownLatch.await(TIME_OUT_SECONDS, TimeUnit.SECONDS)).isTrue(); if (shutdownAfterConsume) { kafkaClient.shutdown(); } - return new JsonPath(cloudEvent.get()); + return cloudEvent.get(); } } diff --git a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow/src/main/java/org/kie/kogito/serverless/workflow/QuarkusKogitoProcessContextResolver.java b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow/src/main/java/org/kie/kogito/serverless/workflow/QuarkusKogitoProcessContextResolver.java index 8e38f722be2..671c4e9e3fb 100644 --- a/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow/src/main/java/org/kie/kogito/serverless/workflow/QuarkusKogitoProcessContextResolver.java +++ b/quarkus/extensions/kogito-quarkus-serverless-workflow-extension/kogito-quarkus-serverless-workflow/src/main/java/org/kie/kogito/serverless/workflow/QuarkusKogitoProcessContextResolver.java @@ -1,17 +1,20 @@ /* - * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * 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 * - * Licensed 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 * - * 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. + * 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.serverless.workflow; diff --git a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/WorkflowProcessor.java b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/WorkflowProcessor.java index a812bd35a99..113abd481fa 100644 --- a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/WorkflowProcessor.java +++ b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/WorkflowProcessor.java @@ -77,7 +77,7 @@ import io.quarkus.vertx.http.deployment.spi.AdditionalStaticResourceBuildItem; import static java.util.Arrays.asList; -import static org.drools.drl.quarkus.util.deployment.DroolsQuarkusResourceUtils.compileGeneratedSources; +import static org.drools.quarkus.util.deployment.DroolsQuarkusResourceUtils.compileGeneratedSources; import static org.kie.kogito.codegen.core.utils.GeneratedFileValidation.validateGeneratedFileTypes; import static org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.dumpFilesToDisk; import static org.kie.kogito.quarkus.common.deployment.KogitoQuarkusResourceUtils.generateAggregatedIndex; diff --git a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/devservices/DataIndexInMemoryContainer.java b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/devservices/DataIndexInMemoryContainer.java index f1beaf4c981..ee5a1593caf 100644 --- a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/devservices/DataIndexInMemoryContainer.java +++ b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common-deployment/src/main/java/org/kie/kogito/quarkus/workflow/deployment/devservices/DataIndexInMemoryContainer.java @@ -18,6 +18,8 @@ */ package org.kie.kogito.quarkus.workflow.deployment.devservices; +import java.time.Duration; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testcontainers.containers.GenericContainer; @@ -60,7 +62,7 @@ public DataIndexInMemoryContainer(DockerImageName dockerImageName, int fixedExpo withEnv("KOGITO_DATA_INDEX_VERTX_GRAPHQL_UI_PATH", "/q/graphql-ui"); withEnv("KOGITO_DATA_INDEX_QUARKUS_PROFILE", "http-events-support"); withExposedPorts(PORT); - waitingFor(Wait.forHttp("/q/health/ready").forStatusCode(200)); + waitingFor(Wait.forHttp("/q/health/ready").forStatusCode(200).withStartupTimeout(Duration.ofMinutes(5))); } @Override diff --git a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/src/main/java/org/kie/kogito/quarkus/workflow/devservices/DataIndexEventPublisher.java b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/src/main/java/org/kie/kogito/quarkus/workflow/devservices/DataIndexEventPublisher.java index 7406838b84b..bf02d1fa339 100644 --- a/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/src/main/java/org/kie/kogito/quarkus/workflow/devservices/DataIndexEventPublisher.java +++ b/quarkus/extensions/kogito-quarkus-workflow-extension-common/kogito-quarkus-workflow-common/src/main/java/org/kie/kogito/quarkus/workflow/devservices/DataIndexEventPublisher.java @@ -38,6 +38,8 @@ public class DataIndexEventPublisher implements EventPublisher { public static final String KOGITO_DATA_INDEX = "kogito.data-index.url"; private static final Logger LOGGER = LoggerFactory.getLogger(DataIndexEventPublisher.class); + private static final String CLOUD_EVENTS_CONTENT_TYPE = "application/cloudevents+json"; + private static final String CONTENT_TYPE = "content-type"; @ConfigProperty(name = KOGITO_DATA_INDEX) Optional dataIndexUrl; @@ -60,8 +62,25 @@ public void publish(DataEvent event) { LOGGER.debug("Sending event to data index: {}", event); switch (event.getType()) { - case "ProcessInstanceEvent": + case "ProcessDefinitionEvent": + webClient.postAbs(dataIndexUrl.get() + "/definitions") + .putHeader(CONTENT_TYPE, CLOUD_EVENTS_CONTENT_TYPE) + .expect(ResponsePredicate.SC_ACCEPTED) + .sendJson(event, result -> { + if (result.failed()) { + LOGGER.error("Failed to send message to Data Index", result.cause()); + } else { + LOGGER.debug("Event published to Data Index"); + } + }); + break; + case "ProcessInstanceErrorDataEvent": + case "ProcessInstanceNodeDataEvent": + case "ProcessInstanceSLADataEvent": + case "ProcessInstanceStateDataEvent": + case "ProcessInstanceVariableDataEvent": webClient.postAbs(dataIndexUrl.get() + "/processes") + .putHeader(CONTENT_TYPE, CLOUD_EVENTS_CONTENT_TYPE) .expect(ResponsePredicate.SC_ACCEPTED) .sendJson(event, result -> { if (result.failed()) { @@ -71,8 +90,14 @@ public void publish(DataEvent event) { } }); break; - case "UserTaskInstanceEvent": + case "UserTaskInstanceAssignmentDataEvent": + case "UserTaskInstanceAttachmentDataEvent": + case "UserTaskInstanceCommentDataEvent": + case "UserTaskInstanceDeadlineDataEvent": + case "UserTaskInstanceStateDataEvent": + case "UserTaskInstanceVariableDataEvent": webClient.postAbs(dataIndexUrl.get() + "/tasks") + .putHeader(CONTENT_TYPE, CLOUD_EVENTS_CONTENT_TYPE) .expect(ResponsePredicate.SC_ACCEPTED) .sendJson(event, result -> { if (result.failed()) { diff --git a/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security-no-auth.yaml b/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security-no-auth.yaml index 428f2a806b2..91bbb72e8cc 100644 --- a/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security-no-auth.yaml +++ b/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security-no-auth.yaml @@ -51,7 +51,6 @@ definitions: type: string required: - userid - additionalProperties: false schemes: - https consumes: diff --git a/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security.yaml b/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security.yaml index b016284c0f3..73fd44b97ed 100644 --- a/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security.yaml +++ b/quarkus/integration-tests/integration-tests-quarkus-openapi-client/src/main/resources/specs/swagger2.0-security.yaml @@ -51,7 +51,6 @@ definitions: type: string required: - userid - additionalProperties: false schemes: - https consumes: diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes/src/main/resources/application.properties b/quarkus/integration-tests/integration-tests-quarkus-processes/src/main/resources/application.properties index 30cf94834ca..58d7ff6dc29 100644 --- a/quarkus/integration-tests/integration-tests-quarkus-processes/src/main/resources/application.properties +++ b/quarkus/integration-tests/integration-tests-quarkus-processes/src/main/resources/application.properties @@ -46,9 +46,6 @@ mp.messaging.outgoing.kogito-usertaskinstances-events.connector=smallrye-kafka mp.messaging.outgoing.kogito-usertaskinstances-events.topic=kogito-usertaskinstances-events mp.messaging.outgoing.kogito-usertaskinstances-events.value.serializer=org.apache.kafka.common.serialization.StringSerializer -mp.messaging.outgoing.kogito-variables-events.connector=smallrye-kafka -mp.messaging.outgoing.kogito-variables-events.topic=kogito-variables-events -mp.messaging.outgoing.kogito-variables-events.value.serializer=org.apache.kafka.common.serialization.StringSerializer quarkus.http.auth.basic=true quarkus.http.auth.permission.default.paths=/handleApprovals/* diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/ProcessEventIT.java b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/ProcessEventIT.java index 0cb8f4498a3..67ece0b69bc 100644 --- a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/ProcessEventIT.java +++ b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/ProcessEventIT.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.kie.kogito.event.process.ProcessDataEvent; +import org.kie.kogito.event.process.ProcessInstanceDataEvent; import org.kie.kogito.test.quarkus.QuarkusTestProperty; import org.kie.kogito.test.quarkus.kafka.KafkaTestClient; import org.kie.kogito.testcontainers.quarkus.KafkaQuarkusTestResource; @@ -55,7 +55,6 @@ class ProcessEventIT { public static final String KOGITO_PROCESSINSTANCES_EVENTS = "kogito-processinstances-events"; public static final String KOGITO_USERTASKINSTANCES_EVENTS = "kogito-usertaskinstances-events"; - public static final String KOGITO_VARIABLE_EVENTS = "kogito-variables-events"; private static Logger LOGGER = LoggerFactory.getLogger(ProcessEventIT.class); @@ -90,14 +89,14 @@ void testSaveTask() throws Exception { String username = "buddy"; String password = "buddy"; - kafkaClient.consume(Set.of(KOGITO_PROCESSINSTANCES_EVENTS, KOGITO_USERTASKINSTANCES_EVENTS, KOGITO_VARIABLE_EVENTS), s -> { + kafkaClient.consume(Set.of(KOGITO_PROCESSINSTANCES_EVENTS, KOGITO_USERTASKINSTANCES_EVENTS), s -> { LOGGER.info("Received from kafka: {}", s); try { - ProcessDataEvent event = mapper.readValue(s, ProcessDataEvent.class); + ProcessInstanceDataEvent event = mapper.readValue(s, ProcessInstanceDataEvent.class); LinkedHashMap data = (LinkedHashMap) event.getData(); if ("handleApprovals".equals(data.get("processId"))) { switch (event.getType()) { - case "ProcessInstanceEvent": + case "ProcessInstanceStateEvent": assertEquals("ProcessInstanceEvent", event.getType()); assertEquals("/handleApprovals", event.getSource().toString()); assertEquals("handleApprovals", data.get("processId")); @@ -106,14 +105,14 @@ void testSaveTask() throws Exception { assertEquals("BPMN", event.getKogitoProcessType()); assertEquals(username, event.getKogitoIdentity()); break; - case "UserTaskInstanceEvent": + case "UserTaskInstanceStateEvent": assertEquals("UserTaskInstanceEvent", event.getType()); assertEquals("/handleApprovals", event.getSource().toString()); assertEquals("handleApprovals", data.get("processId")); assertEquals("1.0", event.getKogitoProcessInstanceVersion()); assertEquals(username, event.getKogitoIdentity()); break; - case "VariableInstanceEvent": + case "ProcessInstanceVariableEvent": assertEquals("VariableInstanceEvent", event.getType()); assertEquals("/handleApprovals", event.getSource().toString()); assertEquals("handleApprovals", data.get("processId")); diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java index 799af8419e2..448036c5805 100644 --- a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java +++ b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java @@ -456,7 +456,11 @@ private static class ClientTaskInfo { } private static class TravellerInputModel { - + public String TaskName; + public String NodeName; + public Boolean Skippable; + public String ActorId; + public String GroupId; public Traveller traveller; } } diff --git a/springboot/addons/events/kafka/src/main/java/org/kie/kogito/events/spring/KafkaEventPublisher.java b/springboot/addons/events/kafka/src/main/java/org/kie/kogito/events/spring/KafkaEventPublisher.java index 83a18c9d9ff..1e164f255f4 100644 --- a/springboot/addons/events/kafka/src/main/java/org/kie/kogito/events/spring/KafkaEventPublisher.java +++ b/springboot/addons/events/kafka/src/main/java/org/kie/kogito/events/spring/KafkaEventPublisher.java @@ -35,10 +35,6 @@ @Component public class KafkaEventPublisher implements EventPublisher { - private static final String PI_TOPIC_NAME = "kogito-processinstances-events"; - private static final String UI_TOPIC_NAME = "kogito-usertaskinstances-events"; - private static final String VI_TOPIC_NAME = "kogito-variables-events"; - private static final Logger logger = LoggerFactory.getLogger(KafkaEventPublisher.class); @Autowired @@ -53,29 +49,33 @@ public class KafkaEventPublisher implements EventPublisher { @Value("${kogito.events.processinstances.enabled:true}") private boolean processInstancesEvents; + @Value("${kogito.events.processdefinitions.enabled:true}") + private boolean processDefinitionEvents; + @Value("${kogito.events.usertasks.enabled:true}") private boolean userTasksEvents; - @Value("${kogito.events.variables.enabled:true}") - private boolean variablesEvents; - @Override public void publish(DataEvent event) { + switch (event.getType()) { - case "ProcessInstanceEvent": - if (processInstancesEvents) { - publishToTopic(event, PI_TOPIC_NAME); - } + case "ProcessInstanceErrorDataEvent": + case "ProcessInstanceNodeDataEvent": + case "ProcessInstanceSLADataEvent": + case "ProcessInstanceStateDataEvent": + case "ProcessInstanceVariableDataEvent": + publishToTopic(event, PROCESS_INSTANCES_TOPIC_NAME); break; - case "UserTaskInstanceEvent": - if (userTasksEvents) { - publishToTopic(event, UI_TOPIC_NAME); - } + case "UserTaskInstanceAssignmentDataEvent": + case "UserTaskInstanceAttachmentDataEvent": + case "UserTaskInstanceCommentDataEvent": + case "UserTaskInstanceDeadlineDataEvent": + case "UserTaskInstanceStateDataEvent": + case "UserTaskInstanceVariableDataEvent": + publishToTopic(event, USER_TASK_INSTANCES_TOPIC_NAME); break; - case "VariableInstanceEvent": - if (variablesEvents) { - publishToTopic(event, VI_TOPIC_NAME); - } + case "ProcessDefinitionEvent": + publishToTopic(event, PROCESS_DEFINITIONS_TOPIC_NAME); break; default: logger.debug("Unknown type of event '{}', ignoring for this publisher", event.getType()); diff --git a/springboot/addons/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisher.java b/springboot/addons/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisher.java index 36d6d13ce61..8ab43d6c7e7 100644 --- a/springboot/addons/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisher.java +++ b/springboot/addons/events/mongodb/src/main/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisher.java @@ -42,9 +42,6 @@ public class SpringbootMongoDBEventPublisher extends MongoDBEventPublisher { @Value("${kogito.events.usertasks.enabled:true}") boolean springEnableUserTasksEvents; - @Value("${kogito.events.variables.enabled:true}") - boolean springEnableVariablesEvents; - @Value("${kogito.events.database:kogito-events}") String springEventsDatabaseName; @@ -54,9 +51,6 @@ public class SpringbootMongoDBEventPublisher extends MongoDBEventPublisher { @Value("${kogito.events.usertasks.collection:kogitousertaskinstancesevents}") String springUserTasksEventsCollectionName; - @Value("${kogito.events.variables.collection:kogitovariablesevents}") - String springVariablesEventsCollectionName; - @PostConstruct public void setupSpringbootMongoDBEventPublisher() { super.configure(); @@ -82,11 +76,6 @@ protected boolean userTasksEvents() { return this.springEnableUserTasksEvents; } - @Override - protected boolean variablesEvents() { - return this.springEnableVariablesEvents; - } - @Override protected String eventsDatabaseName() { return this.springEventsDatabaseName; @@ -102,8 +91,4 @@ protected String userTasksEventsCollection() { return this.springUserTasksEventsCollectionName; } - @Override - protected String variablesEventsCollection() { - return this.springVariablesEventsCollectionName; - } } diff --git a/springboot/addons/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisherTest.java b/springboot/addons/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisherTest.java index 8ce21226073..979411595f9 100644 --- a/springboot/addons/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisherTest.java +++ b/springboot/addons/events/mongodb/src/test/java/org/kie/kogito/events/mongodb/SpringbootMongoDBEventPublisherTest.java @@ -36,8 +36,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -100,11 +100,6 @@ void userTasksEvents() { assertFalse(publisher.userTasksEvents()); } - @Test - void variablesEvents() { - assertFalse(publisher.variablesEvents()); - } - @Test void eventsDatabaseName() { assertEquals("testDB", publisher.eventsDatabaseName()); @@ -120,8 +115,4 @@ void userTasksEventsCollection() { assertEquals("testUTCollection", publisher.userTasksEventsCollection()); } - @Test - void variablesEventsCollection() { - assertEquals("testVCollection", publisher.variablesEventsCollection()); - } } diff --git a/springboot/addons/mail/src/main/java/org/kie/kogito/mail/SpringBootMailSender.java b/springboot/addons/mail/src/main/java/org/kie/kogito/mail/SpringBootMailSender.java index 36700f712b5..f06ca2eba66 100644 --- a/springboot/addons/mail/src/main/java/org/kie/kogito/mail/SpringBootMailSender.java +++ b/springboot/addons/mail/src/main/java/org/kie/kogito/mail/SpringBootMailSender.java @@ -18,7 +18,7 @@ */ package org.kie.kogito.mail; -import org.kie.kogito.event.process.UserTaskDeadlineDataEvent; +import org.kie.kogito.event.usertask.UserTaskInstanceDeadlineDataEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +37,7 @@ public class SpringBootMailSender { @KafkaListener(id = "${kogito.addon.mail.group.id:mail}", topics = "${kogito.events.deadline.topic:kogito-deadline-events}") - public void onMessage(UserTaskDeadlineDataEvent record) { + public void onMessage(UserTaskInstanceDeadlineDataEvent record) { MailInfo mailInfo = MailInfo.of(record.getData()); logger.info("Sending e-mail {}", mailInfo); SimpleMailMessage message = new SimpleMailMessage(); diff --git a/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java b/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java index 524b613ea88..49ab414f0ab 100644 --- a/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java +++ b/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java @@ -28,6 +28,7 @@ import org.kie.kogito.process.workitem.InvalidLifeCyclePhaseException; import org.kie.kogito.process.workitem.InvalidTransitionException; import org.kie.kogito.process.workitem.NotAuthorizedException; +import org.kie.kogito.process.workitem.WorkItemExecutionException; import org.kie.kogito.resource.exceptions.BaseExceptionsHandler; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -123,6 +124,11 @@ public ResponseEntity toResponse(WorkItemNotFoundException exception) { return mapException(exception); } + @ExceptionHandler(WorkItemExecutionException.class) + public ResponseEntity toResponse(WorkItemExecutionException exception) { + return mapException(exception); + } + @ExceptionHandler(VariableViolationException.class) public ResponseEntity toResponse(VariableViolationException exception) { return mapException(exception); diff --git a/springboot/archetype/pom.xml b/springboot/archetype/pom.xml index cca701f3013..d34b0f8ca5b 100644 --- a/springboot/archetype/pom.xml +++ b/springboot/archetype/pom.xml @@ -52,6 +52,10 @@ ${project.version} provided + + org.kie.kogito + kogito-processes-spring-boot-starter + org.kie.kogito kogito-addons-springboot-monitoring-prometheus diff --git a/springboot/archetype/src/main/resources/archetype-resources/src/main/resources/META-INF/resources/index.html b/springboot/archetype/src/main/resources/archetype-resources/src/main/resources/META-INF/resources/index.html index 78ed4c7db28..25c759a475e 100644 --- a/springboot/archetype/src/main/resources/archetype-resources/src/main/resources/META-INF/resources/index.html +++ b/springboot/archetype/src/main/resources/archetype-resources/src/main/resources/META-INF/resources/index.html @@ -29,8 +29,8 @@ - - + +