diff --git a/addons/common/jbpm-usertask-storage-jpa/pom.xml b/addons/common/jbpm-usertask-storage-jpa/pom.xml new file mode 100644 index 00000000000..dd28be272d2 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + org.kie + kogito-addons-common-parent + 999-SNAPSHOT + + + org.jbpm + jbpm-addons-usertask-storage-jpa + + jBPM :: Add-Ons :: User Task Storage JPA :: Common + jBPM Add-Ons User Task Storage JPA Common + + + UTF-8 + org.jbpm.usertask.storage.jpa + + + + + jakarta.persistence + jakarta.persistence-api + + + org.slf4j + slf4j-api + + + org.kie.kogito + kogito-api + + + org.kie.kogito + jbpm-usertask + + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + ch.qos.logback + logback-classic + test + + + org.assertj + assertj-core + test + + + + diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/JPAUserTaskInstances.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/JPAUserTaskInstances.java new file mode 100644 index 00000000000..d2f6a5e4cbf --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/JPAUserTaskInstances.java @@ -0,0 +1,129 @@ +/* + * 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.usertask.jpa; + +import java.util.*; +import java.util.function.Function; + +import org.jbpm.usertask.jpa.mapper.UserTaskInstanceEntityMapper; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.UserTaskInstanceRepository; +import org.kie.kogito.auth.IdentityProvider; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.UserTaskInstances; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JPAUserTaskInstances implements UserTaskInstances { + public static final Logger LOGGER = LoggerFactory.getLogger(JPAUserTaskInstances.class); + + private final UserTaskInstanceRepository userTaskInstanceRepository; + private final UserTaskInstanceEntityMapper userTaskInstanceEntityMapper; + + private Function reconnectUserTaskInstance; + private Function disconnectUserTaskInstance; + + public JPAUserTaskInstances(UserTaskInstanceRepository userTaskInstanceRepository, UserTaskInstanceEntityMapper userTaskInstanceEntityMapper) { + this.userTaskInstanceRepository = userTaskInstanceRepository; + this.userTaskInstanceEntityMapper = userTaskInstanceEntityMapper; + } + + @Override + public Optional findById(String userTaskInstanceId) { + return this.userTaskInstanceRepository.findById(userTaskInstanceId) + .map(userTaskInstanceEntityMapper::mapTaskEntityToInstance) + .map(reconnectUserTaskInstance); + } + + @Override + public List findByIdentity(IdentityProvider identityProvider) { + return userTaskInstanceRepository.findByIdentity(identityProvider) + .stream() + .map(userTaskInstanceEntityMapper::mapTaskEntityToInstance) + .map(reconnectUserTaskInstance) + .toList(); + } + + @Override + public boolean exists(String userTaskInstanceId) { + return userTaskInstanceRepository.findById(userTaskInstanceId).isPresent(); + } + + @Override + public UserTaskInstance create(UserTaskInstance userTaskInstance) { + Optional optional = userTaskInstanceRepository.findById(userTaskInstance.getId()); + + if (optional.isPresent()) { + LOGGER.error("Cannot create userTaskInstance with id {}. Task Already exists.", userTaskInstance.getId()); + throw new IllegalArgumentException("Cannot create userTaskInstance with id " + userTaskInstance.getId() + ". Task Already exists."); + } + + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + entity.setId(userTaskInstance.getId()); + + this.userTaskInstanceRepository.persist(entity); + + userTaskInstanceEntityMapper.mapTaskInstanceToEntity(userTaskInstance, entity); + + return this.reconnectUserTaskInstance.apply(userTaskInstance); + } + + @Override + public UserTaskInstance update(UserTaskInstance userTaskInstance) { + + Optional optional = userTaskInstanceRepository.findById(userTaskInstance.getId()); + + if (optional.isEmpty()) { + LOGGER.error("Could not find userTaskInstance with id {}", userTaskInstance.getId()); + throw new RuntimeException("Could not find userTaskInstance with id " + userTaskInstance.getId()); + } + + UserTaskInstanceEntity userTaskInstanceEntity = optional.get(); + + userTaskInstanceEntityMapper.mapTaskInstanceToEntity(userTaskInstance, userTaskInstanceEntity); + + userTaskInstanceRepository.update(userTaskInstanceEntity); + + return userTaskInstance; + } + + @Override + public UserTaskInstance remove(UserTaskInstance userTaskInstance) { + Optional optional = userTaskInstanceRepository.findById(userTaskInstance.getId()); + + if (optional.isEmpty()) { + LOGGER.warn("Could not remove userTaskInstance with id {}, task cannot be found", userTaskInstance.getId()); + throw new RuntimeException("Could not remove userTaskInstance with id " + userTaskInstance.getId() + ", userTaskInstance cannot be found"); + } + + this.userTaskInstanceRepository.remove(optional.get()); + return this.disconnectUserTaskInstance.apply(userTaskInstance); + } + + @Override + public void setReconnectUserTaskInstance(Function reconnectUserTaskInstance) { + this.reconnectUserTaskInstance = reconnectUserTaskInstance; + } + + @Override + public void setDisconnectUserTaskInstance(Function disconnectUserTaskInstance) { + this.disconnectUserTaskInstance = disconnectUserTaskInstance; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/AttachmentsEntityMapper.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/AttachmentsEntityMapper.java new file mode 100644 index 00000000000..210553ed853 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/AttachmentsEntityMapper.java @@ -0,0 +1,81 @@ +/* + * 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.usertask.jpa.mapper; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jbpm.usertask.jpa.model.AttachmentEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.AttachmentRepository; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.kie.kogito.usertask.model.Attachment; + +import static java.util.stream.Collectors.toCollection; + +public class AttachmentsEntityMapper { + private final AttachmentRepository repository; + + public AttachmentsEntityMapper(AttachmentRepository repository) { + this.repository = repository; + } + + public void mapInstanceToEntity(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + Collection toRemove = userTaskInstanceEntity.getAttachments() + .stream() + .filter(entity -> userTaskInstance.getAttachments().stream().noneMatch(attachment -> attachment.getId().equals(entity.getId()))) + .toList(); + + toRemove.forEach(attachment -> { + repository.remove(attachment); + userTaskInstanceEntity.removeAttachment(attachment); + }); + + userTaskInstance.getAttachments().forEach(attachment -> { + AttachmentEntity attachmentEntity = userTaskInstanceEntity.getAttachments().stream().filter(entity -> entity.getId().equals(attachment.getId())).findFirst().orElseGet(() -> { + AttachmentEntity entity = new AttachmentEntity(); + userTaskInstanceEntity.addAttachment(entity); + return entity; + }); + attachmentEntity.setId(attachment.getId()); + attachmentEntity.setUpdatedBy(attachment.getUpdatedBy()); + attachmentEntity.setName(attachment.getName()); + attachmentEntity.setUrl(attachment.getContent().toString()); + attachmentEntity.setUpdatedAt(attachment.getUpdatedAt()); + }); + } + + public void mapEntityToInstance(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + + List attachments = userTaskInstanceEntity.getAttachments().stream().map(attachmentEntity -> { + Attachment attachment = new Attachment(attachmentEntity.getId(), attachmentEntity.getUpdatedBy()); + attachment.setId(attachmentEntity.getId()); + attachment.setName(attachmentEntity.getName()); + attachment.setContent(URI.create(attachmentEntity.getUrl())); + attachment.setUpdatedAt(attachmentEntity.getUpdatedAt()); + return attachment; + }).collect(toCollection(ArrayList::new)); + + ((DefaultUserTaskInstance) userTaskInstance).setAttachments(attachments); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/CommentsEntityMapper.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/CommentsEntityMapper.java new file mode 100644 index 00000000000..b854ec3510a --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/CommentsEntityMapper.java @@ -0,0 +1,78 @@ +/* + * 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.usertask.jpa.mapper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jbpm.usertask.jpa.model.CommentEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.CommentRepository; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.kie.kogito.usertask.model.Comment; + +import static java.util.stream.Collectors.toCollection; + +public class CommentsEntityMapper { + + private final CommentRepository repository; + + public CommentsEntityMapper(CommentRepository repository) { + this.repository = repository; + } + + public void mapInstanceToEntity(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + Collection toRemove = userTaskInstanceEntity.getComments() + .stream() + .filter(entity -> userTaskInstance.getComments().stream().noneMatch(comment -> comment.getId().equals(entity.getId()))) + .toList(); + + toRemove.forEach(comment -> { + repository.remove(comment); + userTaskInstanceEntity.removeComment(comment); + }); + + userTaskInstance.getComments().forEach(comment -> { + CommentEntity commentEntity = userTaskInstanceEntity.getComments().stream().filter(entity -> entity.getId().equals(comment.getId())).findFirst().orElseGet(() -> { + CommentEntity entity = new CommentEntity(); + userTaskInstanceEntity.addComment(entity); + return entity; + }); + commentEntity.setId(comment.getId()); + commentEntity.setUpdatedBy(comment.getUpdatedBy()); + commentEntity.setComment(comment.getContent()); + commentEntity.setUpdatedAt(comment.getUpdatedAt()); + }); + } + + public void mapEntityToInstance(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + List comments = userTaskInstanceEntity.getComments().stream().map(commentEntity -> { + Comment comment = new Comment(commentEntity.getId(), commentEntity.getUpdatedBy()); + comment.setId(commentEntity.getId()); + comment.setContent(commentEntity.getComment()); + comment.setUpdatedAt(commentEntity.getUpdatedAt()); + return comment; + }).collect(toCollection(ArrayList::new)); + + ((DefaultUserTaskInstance) userTaskInstance).setComments(comments); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskInputsEntityMapper.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskInputsEntityMapper.java new file mode 100644 index 00000000000..12a6c50f986 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskInputsEntityMapper.java @@ -0,0 +1,77 @@ +/* + * 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.usertask.jpa.mapper; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.jbpm.usertask.jpa.mapper.json.utils.JSONUtils; +import org.jbpm.usertask.jpa.model.TaskInputEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.TaskInputRepository; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; + +public class TaskInputsEntityMapper { + + private TaskInputRepository repository; + + public TaskInputsEntityMapper(TaskInputRepository repository) { + this.repository = repository; + } + + public void mapInstanceToEntity(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + Collection toRemove = userTaskInstanceEntity.getInputs() + .stream() + .filter(entity -> !userTaskInstance.getInputs().containsKey(entity.getName())) + .toList(); + + toRemove.forEach(input -> { + repository.remove(input); + userTaskInstanceEntity.removeInput(input); + }); + + userTaskInstance.getInputs().forEach((key, value) -> { + TaskInputEntity inputEntity = userTaskInstanceEntity.getInputs().stream().filter(entity -> entity.getName().equals(key)).findFirst().orElseGet(() -> { + TaskInputEntity entity = new TaskInputEntity(); + entity.setName(key); + userTaskInstanceEntity.addInput(entity); + return entity; + }); + inputEntity.setName(key); + if (Objects.nonNull(value)) { + inputEntity.setValue(JSONUtils.valueToString(value).getBytes(StandardCharsets.UTF_8)); + inputEntity.setJavaType(value.getClass().getName()); + } + }); + } + + public void mapEntityToInstance(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + Map inputs = new HashMap<>(); + userTaskInstanceEntity.getInputs().forEach(taskInputEntity -> { + String value = taskInputEntity.getValue() == null ? null : new String(taskInputEntity.getValue(), StandardCharsets.UTF_8); + inputs.put(taskInputEntity.getName(), JSONUtils.stringTreeToValue(value, taskInputEntity.getJavaType())); + }); + ((DefaultUserTaskInstance) userTaskInstance).setInputs(inputs); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskMetadataEntityMapper.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskMetadataEntityMapper.java new file mode 100644 index 00000000000..999c7357496 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskMetadataEntityMapper.java @@ -0,0 +1,74 @@ +/* + * 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.usertask.jpa.mapper; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.jbpm.usertask.jpa.mapper.json.utils.JSONUtils; +import org.jbpm.usertask.jpa.model.TaskMetadataEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.TaskMetadataRepository; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; + +public class TaskMetadataEntityMapper { + + private final TaskMetadataRepository repository; + + public TaskMetadataEntityMapper(TaskMetadataRepository repository) { + this.repository = repository; + } + + public void mapInstanceToEntity(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + Collection toRemove = userTaskInstanceEntity.getMetadata() + .stream() + .filter(entity -> !userTaskInstance.getMetadata().containsKey(entity.getName())) + .toList(); + + toRemove.forEach(metadata -> { + repository.remove(metadata); + userTaskInstanceEntity.removeMetadata(metadata); + }); + + userTaskInstance.getMetadata().forEach((key, value) -> { + TaskMetadataEntity metadataEntity = userTaskInstanceEntity.getMetadata().stream().filter(entity -> entity.getName().equals(key)).findFirst().orElseGet(() -> { + TaskMetadataEntity entity = new TaskMetadataEntity(); + userTaskInstanceEntity.addMetadata(entity); + return entity; + }); + metadataEntity.setName(key); + if (Objects.nonNull(value)) { + metadataEntity.setValue(JSONUtils.valueToString(value)); + metadataEntity.setJavaType(value.getClass().getName()); + } + }); + } + + public void mapEntityToInstance(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + Map metadata = new HashMap<>(); + userTaskInstanceEntity.getMetadata().forEach(metadataEntry -> { + metadata.put(metadataEntry.getName(), JSONUtils.stringTreeToValue(metadataEntry.getValue(), metadataEntry.getJavaType())); + }); + ((DefaultUserTaskInstance) userTaskInstance).setMetadata(metadata); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskOutputsEntityMapper.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskOutputsEntityMapper.java new file mode 100644 index 00000000000..1fa7d4ae282 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/TaskOutputsEntityMapper.java @@ -0,0 +1,77 @@ +/* + * 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.usertask.jpa.mapper; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import org.jbpm.usertask.jpa.mapper.json.utils.JSONUtils; +import org.jbpm.usertask.jpa.model.TaskOutputEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.TaskOutputRepository; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; + +public class TaskOutputsEntityMapper { + + private final TaskOutputRepository repository; + + public TaskOutputsEntityMapper(TaskOutputRepository repository) { + this.repository = repository; + } + + public void mapInstanceToEntity(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + Collection toRemove = userTaskInstanceEntity.getOutputs() + .stream() + .filter(entity -> !userTaskInstance.getOutputs().containsKey(entity.getName())) + .toList(); + + toRemove.forEach(output -> { + repository.remove(output); + userTaskInstanceEntity.removeOutput(output); + }); + + userTaskInstance.getOutputs().forEach((key, value) -> { + TaskOutputEntity outputEntity = userTaskInstanceEntity.getOutputs().stream().filter(entity -> entity.getName().equals(key)).findFirst().orElseGet(() -> { + TaskOutputEntity entity = new TaskOutputEntity(); + entity.setName(key); + userTaskInstanceEntity.addOutput(entity); + return entity; + }); + outputEntity.setName(key); + if (Objects.nonNull(value)) { + outputEntity.setValue(JSONUtils.valueToString(value).getBytes(StandardCharsets.UTF_8)); + outputEntity.setJavaType(value.getClass().getName()); + } + }); + } + + public void mapEntityToInstance(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + Map outputs = new HashMap<>(); + userTaskInstanceEntity.getOutputs().forEach(taskOutputEntity -> { + String value = taskOutputEntity.getValue() == null ? null : new String(taskOutputEntity.getValue(), StandardCharsets.UTF_8); + outputs.put(taskOutputEntity.getName(), JSONUtils.stringTreeToValue(value, taskOutputEntity.getJavaType())); + }); + ((DefaultUserTaskInstance) userTaskInstance).setOutputs(outputs); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/UserTaskInstanceEntityMapper.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/UserTaskInstanceEntityMapper.java new file mode 100644 index 00000000000..e03125742ba --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/UserTaskInstanceEntityMapper.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.jbpm.usertask.jpa.mapper; + +import java.util.Set; + +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.kie.kogito.usertask.lifecycle.UserTaskState; + +public class UserTaskInstanceEntityMapper { + + private final AttachmentsEntityMapper attachmentsMapper; + private final CommentsEntityMapper commentMapper; + private final TaskInputsEntityMapper taskInputsMapper; + private final TaskOutputsEntityMapper taskOutputsMapper; + private final TaskMetadataEntityMapper taskMetadataMapper; + + public UserTaskInstanceEntityMapper(AttachmentsEntityMapper attachmentsMapper, CommentsEntityMapper commentsMapper, TaskMetadataEntityMapper taskMetadataMapper, + TaskInputsEntityMapper taskInputsMapper, TaskOutputsEntityMapper taskOutputMapper) { + this.attachmentsMapper = attachmentsMapper; + this.commentMapper = commentsMapper; + this.taskMetadataMapper = taskMetadataMapper; + this.taskInputsMapper = taskInputsMapper; + this.taskOutputsMapper = taskOutputMapper; + } + + public UserTaskInstanceEntity mapTaskInstanceToEntity(UserTaskInstance userTaskInstance, UserTaskInstanceEntity entity) { + entity.setId(userTaskInstance.getId()); + entity.setTaskName(userTaskInstance.getTaskName()); + entity.setTaskDescription(userTaskInstance.getTaskDescription()); + entity.setTaskPriority(userTaskInstance.getTaskPriority()); + entity.setStatus(userTaskInstance.getStatus().getName()); + entity.setTerminationType(userTaskInstance.getStatus().getTerminate() == null ? null : userTaskInstance.getStatus().getTerminate().name()); + entity.setExternalReferenceId(userTaskInstance.getExternalReferenceId()); + entity.setUserTaskId(userTaskInstance.getUserTaskId()); + + entity.setActualOwner(userTaskInstance.getActualOwner()); + entity.setPotentialUsers(Set.copyOf(userTaskInstance.getPotentialUsers())); + entity.setPotentialGroups(Set.copyOf(userTaskInstance.getPotentialGroups())); + entity.setAdminUsers(Set.copyOf(userTaskInstance.getAdminUsers())); + entity.setAdminGroups(Set.copyOf(userTaskInstance.getAdminGroups())); + entity.setExcludedUsers(Set.copyOf(userTaskInstance.getExcludedUsers())); + + attachmentsMapper.mapInstanceToEntity(userTaskInstance, entity); + commentMapper.mapInstanceToEntity(userTaskInstance, entity); + taskInputsMapper.mapInstanceToEntity(userTaskInstance, entity); + taskOutputsMapper.mapInstanceToEntity(userTaskInstance, entity); + taskMetadataMapper.mapInstanceToEntity(userTaskInstance, entity); + + return entity; + } + + public UserTaskInstance mapTaskEntityToInstance(UserTaskInstanceEntity entity) { + + DefaultUserTaskInstance instance = new DefaultUserTaskInstance(); + + instance.setId(entity.getId()); + instance.setUserTaskId(entity.getUserTaskId()); + instance.setExternalReferenceId(entity.getExternalReferenceId()); + instance.setTaskName(entity.getTaskName()); + instance.setTaskDescription(entity.getTaskDescription()); + instance.setTaskPriority(entity.getTaskPriority()); + + UserTaskState.TerminationType terminationType = entity.getTerminationType() == null ? null : UserTaskState.TerminationType.valueOf(entity.getTerminationType()); + instance.setStatus(UserTaskState.of(entity.getStatus(), terminationType)); + + instance.setActualOwner(entity.getActualOwner()); + instance.setPotentialUsers(Set.copyOf(entity.getPotentialUsers())); + instance.setPotentialGroups(Set.copyOf(entity.getPotentialGroups())); + instance.setAdminUsers(Set.copyOf(entity.getAdminUsers())); + instance.setAdminGroups(Set.copyOf(entity.getAdminGroups())); + instance.setExcludedUsers(Set.copyOf(entity.getExcludedUsers())); + + attachmentsMapper.mapEntityToInstance(entity, instance); + commentMapper.mapEntityToInstance(entity, instance); + taskInputsMapper.mapEntityToInstance(entity, instance); + taskOutputsMapper.mapEntityToInstance(entity, instance); + taskMetadataMapper.mapEntityToInstance(entity, instance); + + return instance; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/json/utils/JSONUtils.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/json/utils/JSONUtils.java new file mode 100644 index 00000000000..b7e33589800 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/mapper/json/utils/JSONUtils.java @@ -0,0 +1,54 @@ +/* + * 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.usertask.jpa.mapper.json.utils; + +import java.util.Objects; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +public class JSONUtils { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + static { + OBJECT_MAPPER.registerModule(new JavaTimeModule()); + } + + public static String valueToString(Object value) { + try { + return OBJECT_MAPPER.writeValueAsString(value); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static Object stringTreeToValue(String value, String javaType) { + try { + if (Objects.isNull(value) || Objects.isNull(javaType)) { + return null; + } + return OBJECT_MAPPER.readValue(value, Class.forName(javaType)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/AttachmentEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/AttachmentEntity.java new file mode 100644 index 00000000000..a0bff107682 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/AttachmentEntity.java @@ -0,0 +1,95 @@ +/* + * 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.usertask.jpa.model; + +import java.util.Date; + +import jakarta.persistence.*; + +@Entity +@Table(name = "jbpm_user_tasks_attachments") +public class AttachmentEntity { + + @Id + private String id; + + private String name; + + private String url; + + @Column(name = "updated_by") + private String updatedBy; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "updated_at") + private Date updatedAt; + + @ManyToOne + @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "fk_user_task_attachment_tid")) + private UserTaskInstanceEntity taskInstance; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public String getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + public UserTaskInstanceEntity getTaskInstance() { + return taskInstance; + } + + public void setTaskInstance(UserTaskInstanceEntity taskInstance) { + this.taskInstance = taskInstance; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/CommentEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/CommentEntity.java new file mode 100644 index 00000000000..cf70f4e7bca --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/CommentEntity.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jbpm.usertask.jpa.model; + +import java.util.Date; + +import jakarta.persistence.*; + +@Entity +@Table(name = "jbpm_user_tasks_comments") +public class CommentEntity { + + @Id + private String id; + + private String comment; + + @Column(name = "updated_by") + private String updatedBy; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "updated_at") + private Date updatedAt; + + @ManyToOne(optional = false) + @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "fk_user_task_comment_tid")) + private UserTaskInstanceEntity taskInstance; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public String getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(String user) { + this.updatedBy = user; + } + + public UserTaskInstanceEntity getTaskInstance() { + return taskInstance; + } + + public void setTaskInstance(UserTaskInstanceEntity taskInstance) { + this.taskInstance = taskInstance; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskDataEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskDataEntity.java new file mode 100644 index 00000000000..506f3bf925b --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskDataEntity.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jbpm.usertask.jpa.model; + +import java.util.Objects; + +import jakarta.persistence.*; + +@MappedSuperclass +public abstract class TaskDataEntity { + + @Id + @Column(name = "name") + protected String name; + + @Id + @ManyToOne(optional = false) + @JoinColumn(name = "task_id") + protected UserTaskInstanceEntity taskInstance; + + @Column(name = "value") + protected T value; + + @Column(name = "java_type") + protected String javaType; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public UserTaskInstanceEntity getTaskInstance() { + return taskInstance; + } + + public void setTaskInstance(UserTaskInstanceEntity taskInstance) { + this.taskInstance = taskInstance; + } + + public T getValue() { + return value; + } + + public void setValue(T value) { + this.value = value; + } + + public String getJavaType() { + return javaType; + } + + public void setJavaType(String javaType) { + this.javaType = javaType; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + TaskDataEntity that = (TaskDataEntity) o; + return Objects.equals(getName(), that.getName()) && Objects.equals(getTaskInstance(), that.getTaskInstance()) && Objects.equals(getValue(), + that.getValue()) && Objects.equals(getJavaType(), that.getJavaType()); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getTaskInstance(), getValue(), getJavaType()); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskDataEntityPK.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskDataEntityPK.java new file mode 100644 index 00000000000..4d0f1fab9ed --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskDataEntityPK.java @@ -0,0 +1,76 @@ +/* + * 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.usertask.jpa.model; + +import java.io.Serializable; +import java.util.Objects; + +public class TaskDataEntityPK implements Serializable { + + private String name; + private UserTaskInstanceEntity taskInstance; + + public TaskDataEntityPK() { + } + + public TaskDataEntityPK(String inputName, UserTaskInstanceEntity taskInstance) { + this.taskInstance = taskInstance; + this.name = inputName; + } + + public UserTaskInstanceEntity getTaskInstance() { + return taskInstance; + } + + public void setTaskInstance(UserTaskInstanceEntity taskInstance) { + this.taskInstance = taskInstance; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + TaskDataEntityPK that = (TaskDataEntityPK) o; + return Objects.equals(getName(), that.getName()) && Objects.equals(getTaskInstance(), that.getTaskInstance()); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getTaskInstance()); + } + + @Override + public String toString() { + return "TaskInputEntityId{" + + "taskInstance='" + taskInstance + '\'' + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskInputEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskInputEntity.java new file mode 100644 index 00000000000..9c4351cfd24 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskInputEntity.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "jbpm_user_tasks_inputs") +@AttributeOverrides({ + @AttributeOverride(name = "name", column = @Column(name = "input_name")), + @AttributeOverride(name = "value", column = @Column(name = "input_value")) +}) +@AssociationOverride(name = "taskInstance", foreignKey = @ForeignKey(name = "jbpm_user_tasks_inputs_tid")) +@IdClass(TaskDataEntityPK.class) +public class TaskInputEntity extends TaskDataEntity { + +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskMetadataEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskMetadataEntity.java new file mode 100644 index 00000000000..2729ee68716 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskMetadataEntity.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "jbpm_user_tasks_metadata") +@AttributeOverrides({ + @AttributeOverride(name = "name", column = @Column(name = "metadata_name")), + @AttributeOverride(name = "value", column = @Column(name = "metadata_value")) +}) +@AssociationOverride(name = "taskInstance", + joinColumns = @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "jbpm_user_tasks_metadata_tid"))) +@IdClass(TaskDataEntityPK.class) +public class TaskMetadataEntity extends TaskDataEntity { + +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskOutputEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskOutputEntity.java new file mode 100644 index 00000000000..bd7098f2450 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/TaskOutputEntity.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "jbpm_user_tasks_outputs") +@AttributeOverrides({ + @AttributeOverride(name = "name", column = @Column(name = "output_name")), + @AttributeOverride(name = "value", column = @Column(name = "output_value")) +}) +@AssociationOverride(name = "taskInstance", + joinColumns = @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "jbpm_user_tasks_outputs_tid"))) +@IdClass(TaskDataEntityPK.class) +public class TaskOutputEntity extends TaskDataEntity { + +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/UserTaskInstanceEntity.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/UserTaskInstanceEntity.java new file mode 100644 index 00000000000..8b3cfca0282 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/model/UserTaskInstanceEntity.java @@ -0,0 +1,334 @@ +/* + * 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.usertask.jpa.model; + +import java.util.*; + +import jakarta.persistence.*; + +@Entity +@NamedQuery(name = UserTaskInstanceEntity.GET_INSTANCES_BY_IDENTITY, + query = "select userTask from UserTaskInstanceEntity userTask " + + "left join userTask.adminGroups adminGroups " + + "left join userTask.potentialGroups potentialGroups " + + "where userTask.actualOwner = :userId " + + "or :userId member of userTask.adminUsers " + + "or adminGroups in (:roles) " + + "or (:userId member of userTask.potentialUsers and :userId not member of userTask.excludedUsers) " + + "or potentialGroups in (:roles)") +@Table(name = "jbpm_user_tasks") +public class UserTaskInstanceEntity { + public static final String GET_INSTANCES_BY_IDENTITY = "UserTaskInstanceEntity.GetInstanceByIdentity"; + + @Id + private String id; + + @Column(name = "user_task_id") + private String userTaskId; + + @Column(name = "task_name") + private String taskName; + + @Column(name = "task_description") + private String taskDescription; + + @Column(name = "task_priority") + private String taskPriority; + + private String status; + + @Column(name = "termination_type") + private String terminationType; + + @Column(name = "actual_owner") + private String actualOwner; + + @Column(name = "external_reference_id") + private String externalReferenceId; + + @ElementCollection + @CollectionTable(name = "jbpm_user_tasks_potential_users", joinColumns = @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "fk_jbpm_user_tasks_potential_users_tid"))) + @Column(name = "user_id", nullable = false) + private Set potentialUsers = new HashSet<>(); + + @ElementCollection + @CollectionTable(name = "jbpm_user_tasks_potential_groups", joinColumns = @JoinColumn(name = "task_id"), + foreignKey = @ForeignKey(name = "fk_jbpm_user_tasks_potential_groups_tid")) + @Column(name = "group_id") + private Set potentialGroups = new HashSet<>(); + + @ElementCollection + @CollectionTable(name = "jbpm_user_tasks_admin_users", joinColumns = @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "fk_jbpm_user_tasks_admin_users_tid"))) + @Column(name = "user_id", nullable = false) + private Set adminUsers = new HashSet<>(); + + @ElementCollection + @CollectionTable(name = "jbpm_user_tasks_admin_groups", joinColumns = @JoinColumn(name = "task_id"), + foreignKey = @ForeignKey(name = "fk_jbpm_user_tasks_admin_groups_tid")) + @Column(name = "group_id") + private Set adminGroups = new HashSet<>(); + + @ElementCollection + @CollectionTable(name = "jbpm_user_tasks_excluded_users", joinColumns = @JoinColumn(name = "task_id", foreignKey = @ForeignKey(name = "fk_jbpm_user_tasks_excluded_users_tid"))) + @Column(name = "user_id", nullable = false) + private Set excludedUsers = new HashSet<>(); + + @OneToMany(mappedBy = "taskInstance", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List attachments = new ArrayList<>(); + + @OneToMany(mappedBy = "taskInstance", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List comments = new ArrayList<>(); + + @OneToMany(mappedBy = "taskInstance", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List inputs = new ArrayList<>(); + + @OneToMany(mappedBy = "taskInstance", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List outputs = new ArrayList<>(); + + @OneToMany(mappedBy = "taskInstance", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List metadata = new ArrayList<>(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getActualOwner() { + return actualOwner; + } + + public void setActualOwner(String actualOwner) { + this.actualOwner = actualOwner; + } + + public String getTaskName() { + return taskName; + } + + public void setTaskName(String taskName) { + this.taskName = taskName; + } + + public String getTaskDescription() { + return taskDescription; + } + + public void setTaskDescription(String taskDescription) { + this.taskDescription = taskDescription; + } + + public String getTaskPriority() { + return taskPriority; + } + + public void setTaskPriority(String taskPriority) { + this.taskPriority = taskPriority; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getExternalReferenceId() { + return externalReferenceId; + } + + public void setExternalReferenceId(String externalReferenceId) { + this.externalReferenceId = externalReferenceId; + } + + public void setPotentialUsers(Set potentialUsers) { + this.potentialUsers.clear(); + this.potentialUsers.addAll(potentialUsers); + } + + public Set getPotentialUsers() { + return potentialUsers; + } + + public Set getPotentialGroups() { + return potentialGroups; + } + + public void setPotentialGroups(Set potentialGroups) { + this.potentialGroups.clear(); + this.potentialGroups.addAll(potentialGroups); + } + + public Set getAdminUsers() { + return adminUsers; + } + + public void setAdminUsers(Set adminUsers) { + this.adminUsers.clear(); + this.adminUsers.addAll(adminUsers); + } + + public Collection getAdminGroups() { + return adminGroups; + } + + public void setAdminGroups(Set adminGroups) { + this.adminGroups.clear(); + this.adminGroups.addAll(adminGroups); + } + + public Collection getExcludedUsers() { + return excludedUsers; + } + + public void setExcludedUsers(Set excludedUsers) { + this.excludedUsers.clear(); + this.excludedUsers.addAll(excludedUsers); + } + + public void clearAttachments() { + this.attachments.clear(); + } + + public Collection getAttachments() { + return attachments; + } + + public void addAttachment(AttachmentEntity attachment) { + attachment.setTaskInstance(this); + this.attachments.add(attachment); + } + + public void removeAttachment(AttachmentEntity attachmentEntity) { + this.attachments.remove(attachmentEntity); + } + + public void setAttachments(Collection attachments) { + this.clearAttachments(); + this.attachments.addAll(attachments); + } + + public void clearComments() { + this.comments.clear(); + } + + public void removeComment(CommentEntity comment) { + this.comments.remove(comment); + } + + public Collection getComments() { + return comments; + } + + public void addComment(CommentEntity comment) { + comment.setTaskInstance(this); + this.comments.add(comment); + } + + public void setComments(Collection comments) { + this.clearComments(); + this.comments.addAll(comments); + } + + public void clearInputs() { + this.inputs.clear(); + } + + public Collection getInputs() { + return inputs; + } + + public void setInputs(Collection inputs) { + this.clearInputs(); + this.inputs.addAll(inputs); + } + + public void addInput(TaskInputEntity input) { + input.setTaskInstance(this); + this.inputs.add(input); + } + + public void removeInput(TaskInputEntity input) { + this.inputs.remove(input); + } + + public void clearOutputs() { + this.outputs.clear(); + } + + public Collection getOutputs() { + return outputs; + } + + public void addOutput(TaskOutputEntity output) { + output.setTaskInstance(this); + this.outputs.add(output); + } + + public void removeOutput(TaskOutputEntity output) { + this.outputs.remove(output); + } + + public void setOutputs(Collection outputs) { + this.clearOutputs(); + this.outputs.addAll(outputs); + } + + public void clearMetadata() { + this.metadata.clear(); + } + + public Collection getMetadata() { + return metadata; + } + + public void addMetadata(TaskMetadataEntity metadata) { + metadata.setTaskInstance(this); + this.metadata.add(metadata); + } + + public void removeMetadata(TaskMetadataEntity metadata) { + this.metadata.remove(metadata); + } + + public void setMetadata(Collection metadata) { + this.clearMetadata(); + this.metadata.addAll(metadata); + } + + public void setUserTaskId(String userTaskId) { + this.userTaskId = userTaskId; + } + + public String getUserTaskId() { + return userTaskId; + } + + public void setTerminationType(String terminationType) { + this.terminationType = terminationType; + } + + public String getTerminationType() { + return terminationType; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/AttachmentRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/AttachmentRepository.java new file mode 100644 index 00000000000..92bf5f5a81f --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/AttachmentRepository.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.repository; + +import org.jbpm.usertask.jpa.model.AttachmentEntity; + +public class AttachmentRepository extends BaseRepository { + + public AttachmentRepository(UserTaskJPAContext context) { + super(context); + } + + @Override + public Class getEntityClass() { + return AttachmentEntity.class; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/BaseRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/BaseRepository.java new file mode 100644 index 00000000000..ed144ddbc04 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/BaseRepository.java @@ -0,0 +1,63 @@ +/* + * 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.usertask.jpa.repository; + +import java.util.List; +import java.util.Optional; + +import jakarta.persistence.EntityManager; + +public abstract class BaseRepository { + + protected UserTaskJPAContext context; + + public BaseRepository(UserTaskJPAContext context) { + this.context = context; + } + + public Optional findById(K id) { + return Optional.ofNullable(getEntityManager().find(getEntityClass(), id)); + } + + public List findAll() { + return getEntityManager().createQuery("from " + getEntityClass().getName(), getEntityClass()).getResultList(); + } + + public T persist(T entity) { + getEntityManager().persist(entity); + + return entity; + } + + public T update(T entity) { + return this.getEntityManager().merge(entity); + } + + public T remove(T entity) { + this.getEntityManager().remove(entity); + return entity; + } + + public abstract Class getEntityClass(); + + protected EntityManager getEntityManager() { + return context.getEntityManager(); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/CommentRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/CommentRepository.java new file mode 100644 index 00000000000..98b85d6a991 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/CommentRepository.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.repository; + +import org.jbpm.usertask.jpa.model.CommentEntity; + +public class CommentRepository extends BaseRepository { + + public CommentRepository(UserTaskJPAContext context) { + super(context); + } + + @Override + public Class getEntityClass() { + return CommentEntity.class; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskInputRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskInputRepository.java new file mode 100644 index 00000000000..6e85081ff76 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskInputRepository.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.repository; + +import org.jbpm.usertask.jpa.model.TaskDataEntityPK; +import org.jbpm.usertask.jpa.model.TaskInputEntity; + +public class TaskInputRepository extends BaseRepository { + + public TaskInputRepository(UserTaskJPAContext context) { + super(context); + } + + @Override + public Class getEntityClass() { + return TaskInputEntity.class; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskMetadataRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskMetadataRepository.java new file mode 100644 index 00000000000..26796bb38aa --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskMetadataRepository.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.repository; + +import org.jbpm.usertask.jpa.model.TaskDataEntityPK; +import org.jbpm.usertask.jpa.model.TaskMetadataEntity; + +public class TaskMetadataRepository extends BaseRepository { + + public TaskMetadataRepository(UserTaskJPAContext context) { + super(context); + } + + @Override + public Class getEntityClass() { + return TaskMetadataEntity.class; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskOutputRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskOutputRepository.java new file mode 100644 index 00000000000..2b39b8f1bb0 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/TaskOutputRepository.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.repository; + +import org.jbpm.usertask.jpa.model.TaskDataEntityPK; +import org.jbpm.usertask.jpa.model.TaskOutputEntity; + +public class TaskOutputRepository extends BaseRepository { + + public TaskOutputRepository(UserTaskJPAContext context) { + super(context); + } + + @Override + public Class getEntityClass() { + return TaskOutputEntity.class; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/UserTaskInstanceRepository.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/UserTaskInstanceRepository.java new file mode 100644 index 00000000000..1be6a4aec71 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/UserTaskInstanceRepository.java @@ -0,0 +1,48 @@ +/* + * 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.usertask.jpa.repository; + +import java.util.List; + +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.kie.kogito.auth.IdentityProvider; + +import jakarta.persistence.TypedQuery; + +import static org.jbpm.usertask.jpa.model.UserTaskInstanceEntity.GET_INSTANCES_BY_IDENTITY; + +public class UserTaskInstanceRepository extends BaseRepository { + + public UserTaskInstanceRepository(UserTaskJPAContext context) { + super(context); + } + + public List findByIdentity(IdentityProvider identityProvider) { + TypedQuery query = getEntityManager().createNamedQuery(GET_INSTANCES_BY_IDENTITY, UserTaskInstanceEntity.class); + query.setParameter("userId", identityProvider.getName()); + query.setParameter("roles", identityProvider.getRoles()); + return query.getResultList(); + } + + @Override + public Class getEntityClass() { + return UserTaskInstanceEntity.class; + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/UserTaskJPAContext.java b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/UserTaskJPAContext.java new file mode 100644 index 00000000000..8606184dd58 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/repository/UserTaskJPAContext.java @@ -0,0 +1,27 @@ +/* + * 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.usertask.jpa.repository; + +import jakarta.persistence.EntityManager; + +public interface UserTaskJPAContext { + + EntityManager getEntityManager(); +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/resources/META-INF/beans.xml b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/resources/META-INF/kie-flyway.properties b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/META-INF/kie-flyway.properties new file mode 100644 index 00000000000..67ce94390d9 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/META-INF/kie-flyway.properties @@ -0,0 +1,23 @@ +# +# 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. +# + +module.name=jbpm-user-task-storage + +module.locations.h2=classpath:kie-flyway/db/user-tasks/h2 +module.locations.postgresql=classpath:kie-flyway/db/user-tasks/postgresql \ No newline at end of file diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/resources/kie-flyway/db/user-tasks/h2/V1.0.0__jBPM_user_task_create.sql b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/kie-flyway/db/user-tasks/h2/V1.0.0__jBPM_user_task_create.sql new file mode 100644 index 00000000000..058f3599d3b --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/kie-flyway/db/user-tasks/h2/V1.0.0__jBPM_user_task_create.sql @@ -0,0 +1,166 @@ +/* + * 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. + */ + +create table jbpm_user_tasks ( + id varchar(50) not null, + user_task_id varchar(255), + task_priority varchar(50), + actual_owner varchar(255), + task_description varchar(255), + status varchar(255), + termination_type varchar(255), + external_reference_id varchar(255), + task_name varchar(255), + primary key (id) +); + +create table jbpm_user_tasks_potential_users( + task_id varchar(50) not null, + user_id varchar(255) not null, + primary key (task_id, user_id) +); + +create table jbpm_user_tasks_potential_groups( + task_id varchar(50) not null, + group_id varchar(255) not null, + primary key (task_id, group_id) +); + +create table jbpm_user_tasks_admin_users ( + task_id varchar(50) not null, + user_id varchar(255) not null, + primary key (task_id, user_id) +); + +create table jbpm_user_tasks_admin_groups ( + task_id varchar(50) not null, + group_id varchar(255) not null, + primary key (task_id, group_id) +); + +create table jbpm_user_tasks_excluded_users( + task_id varchar(50) not null, + user_id varchar(255) not null, + primary key (task_id, user_id) +); + +create table jbpm_user_tasks_attachments ( + id varchar(50) not null, + name varchar(255), + updated_by varchar(255), + updated_at timestamp, + url varchar(255), + task_id varchar(50) not null, + primary key (id) +); + +create table jbpm_user_tasks_comments ( + id varchar(50) not null, + updated_by varchar(255), + updated_at timestamp, + comment varchar(255), + task_id varchar(50) not null, + primary key (id) +); + +create table jbpm_user_tasks_inputs ( + task_id varchar(50) not null, + input_name varchar(255) not null, + input_value varbinary(max), + java_type varchar(255), + primary key (task_id, input_name) +); + +create table jbpm_user_tasks_outputs ( + task_id varchar(50) not null, + output_name varchar(255) not null, + output_value varbinary(max), + java_type varchar(255), + primary key (task_id, output_name) +); + +create table jbpm_user_tasks_metadata ( + task_id varchar(50) not null, + metadata_name varchar(255) not null, + metadata_value varchar(512), + java_type varchar(255), + primary key (task_id, metadata_name) +); + +alter table if exists jbpm_user_tasks_potential_users +drop constraint if exists fk_jbpm_user_tasks_potential_users_tid cascade; + +alter table if exists jbpm_user_tasks_potential_users +add constraint fk_jbpm_user_fk_tasks_potential_users_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_potential_groups +drop constraint if exists fk_jbpm_user_tasks_potential_groups_tid cascade; + +alter table if exists jbpm_user_tasks_potential_groups +add constraint fk_jbpm_user_tasks_potential_groups_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_admin_users +drop constraint if exists fk_jbpm_user_tasks_admin_users_tid cascade; + +alter table if exists jbpm_user_tasks_admin_users +add constraint fk_jbpm_user_tasks_admin_users_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_admin_groups +drop constraint if exists fk_jbpm_user_tasks_admin_groups_tid cascade; + +alter table if exists jbpm_user_tasks_admin_groups +add constraint fk_jbpm_user_tasks_admin_groups_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_excluded_users +drop constraint if exists fk_jbpm_user_tasks_excluded_users_tid cascade; + +alter table if exists jbpm_user_tasks_excluded_users +add constraint fk_jbpm_user_tasks_excluded_users_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_attachments +drop constraint if exists fk_user_task_attachment_tid cascade; + +alter table if exists jbpm_user_tasks_attachments +add constraint fk_user_task_attachment_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_comments +drop constraint if exists fk_user_task_comment_tid cascade; + +alter table if exists jbpm_user_tasks_comments +add constraint fk_user_task_comment_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_inputs +drop constraint if exists fk_jbpm_user_tasks_inputs_tid cascade; + +alter table if exists jbpm_user_tasks_inputs +add constraint fk_jbpm_user_tasks_inputs_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_outputs +drop constraint if exists fk_jbpm_user_tasks_outputs_tid cascade; + +alter table if exists jbpm_user_tasks_outputs +add constraint fk_jbpm_user_tasks_outputs_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_metadata +drop constraint if exists fk_jbpm_user_tasks_metadata_tid cascade; + +alter table if exists jbpm_user_tasks_metadata +add constraint fk_jbpm_user_tasks_metadata_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + + diff --git a/addons/common/jbpm-usertask-storage-jpa/src/main/resources/kie-flyway/db/user-tasks/postgresql/V1.0.0__jBPM_user_task_create.sql b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/kie-flyway/db/user-tasks/postgresql/V1.0.0__jBPM_user_task_create.sql new file mode 100644 index 00000000000..8daa0437216 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/main/resources/kie-flyway/db/user-tasks/postgresql/V1.0.0__jBPM_user_task_create.sql @@ -0,0 +1,164 @@ +/* + * 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. + */ + +create table jbpm_user_tasks ( + id varchar(50) not null, + user_task_id varchar(255), + task_priority varchar(50), + actual_owner varchar(255), + task_description varchar(255), + status varchar(255), + termination_type varchar(255), + external_reference_id varchar(255), + task_name varchar(255), + primary key (id) +); + +create table jbpm_user_tasks_potential_users( + task_id varchar(50) not null, + user_id varchar(255) not null, + primary key (task_id, user_id) +); + +create table jbpm_user_tasks_potential_groups( + task_id varchar(50) not null, + group_id varchar(255) not null, + primary key (task_id, group_id) +); + +create table jbpm_user_tasks_admin_users ( + task_id varchar(50) not null, + user_id varchar(255) not null, + primary key (task_id, user_id) +); + +create table jbpm_user_tasks_admin_groups ( + task_id varchar(50) not null, + group_id varchar(255) not null, + primary key (task_id, group_id) +); + +create table jbpm_user_tasks_excluded_users( + task_id varchar(50) not null, + user_id varchar(255) not null, + primary key (task_id, user_id) +); + +create table jbpm_user_tasks_attachments ( + id varchar(50) not null, + name varchar(255), + updated_by varchar(255), + updated_at timestamp(6), + url varchar(255), + task_id varchar(50) not null, + primary key (id) +); + +create table jbpm_user_tasks_comments ( + id varchar(50) not null, + updated_by varchar(255), + updated_at timestamp(6), + comment varchar(255), + task_id varchar(50) not null, + primary key (id) +); + +create table jbpm_user_tasks_inputs ( + task_id varchar(50) not null, + input_name varchar(255) not null, + input_value bytea, + java_type varchar(255), + primary key (task_id, input_name) +); + +create table jbpm_user_tasks_outputs ( + task_id varchar(50) not null, + output_name varchar(255) not null, + output_value bytea, + java_type varchar(255), + primary key (task_id, output_name) +); + +create table jbpm_user_tasks_metadata ( + task_id varchar(50), + metadata_name varchar(255) not null, + metadata_value varchar(512), + java_type varchar(255), + primary key (task_id, metadata_name) +); + +alter table if exists jbpm_user_tasks_potential_users +drop constraint if exists fk_jbpm_user_tasks_potential_users_tid cascade; + +alter table if exists jbpm_user_tasks_potential_users +add constraint fk_jbpm_user_fk_tasks_potential_users_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_potential_groups +drop constraint if exists fk_jbpm_user_tasks_potential_groups_tid cascade; + +alter table if exists jbpm_user_tasks_potential_groups +add constraint fk_jbpm_user_tasks_potential_groups_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_admin_users +drop constraint if exists fk_jbpm_user_tasks_admin_users_tid cascade; + +alter table if exists jbpm_user_tasks_admin_users +add constraint fk_jbpm_user_tasks_admin_users_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_admin_groups +drop constraint if exists fk_jbpm_user_tasks_admin_groups_tid cascade; + +alter table if exists jbpm_user_tasks_admin_groups +add constraint fk_jbpm_user_tasks_admin_groups_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_excluded_users +drop constraint if exists fk_jbpm_user_tasks_excluded_users_tid cascade; + +alter table if exists jbpm_user_tasks_excluded_users +add constraint fk_jbpm_user_tasks_excluded_users_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_attachments +drop constraint if exists fk_user_task_attachment_tid cascade; + +alter table if exists jbpm_user_tasks_attachments +add constraint fk_user_task_attachment_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_comments +drop constraint if exists fk_user_task_comment_tid cascade; + +alter table if exists jbpm_user_tasks_comments +add constraint fk_user_task_comment_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_inputs +drop constraint if exists fk_jbpm_user_tasks_inputs_tid cascade; + +alter table if exists jbpm_user_tasks_inputs +add constraint fk_jbpm_user_tasks_inputs_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_outputs +drop constraint if exists fk_jbpm_user_tasks_outputs_tid cascade; + +alter table if exists jbpm_user_tasks_outputs +add constraint fk_jbpm_user_tasks_outputs_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; + +alter table if exists jbpm_user_tasks_metadata +drop constraint if exists fk_jbpm_user_tasks_metadata_tid cascade; + +alter table if exists jbpm_user_tasks_metadata +add constraint fk_jbpm_user_tasks_metadata_tid foreign key (task_id) references jbpm_user_tasks(id) on delete cascade; \ No newline at end of file diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/JPAUserTaskInstancesTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/JPAUserTaskInstancesTest.java new file mode 100644 index 00000000000..d0ca49f1143 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/JPAUserTaskInstancesTest.java @@ -0,0 +1,220 @@ +/* + * 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.usertask.jpa; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.*; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.UserTaskInstanceRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.auth.IdentityProviders; +import org.kie.kogito.usertask.UserTaskInstance; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class JPAUserTaskInstancesTest { + + @Mock + private UserTaskInstanceRepository userTaskInstanceRepository; + + @Mock + private AttachmentsEntityMapper attachmentsEntityMapper; + @Mock + private CommentsEntityMapper commentsEntityMapper; + @Mock + private TaskMetadataEntityMapper metadataEntityMapper; + @Mock + private TaskInputsEntityMapper inputsEntityMapper; + @Mock + private TaskOutputsEntityMapper outputsEntityMapper; + + private UserTaskInstanceEntityMapper userTaskInstanceEntityMapper; + @Mock + private Function reconnectUserTaskInstance; + @Mock + private Function disconnectUserTaskInstance; + + private JPAUserTaskInstances jpaUserTaskInstances; + + @BeforeEach + public void setup() { + userTaskInstanceEntityMapper = spy(new UserTaskInstanceEntityMapper(attachmentsEntityMapper, commentsEntityMapper, metadataEntityMapper, inputsEntityMapper, outputsEntityMapper)); + jpaUserTaskInstances = new JPAUserTaskInstances(userTaskInstanceRepository, userTaskInstanceEntityMapper); + jpaUserTaskInstances.setReconnectUserTaskInstance(reconnectUserTaskInstance); + jpaUserTaskInstances.setDisconnectUserTaskInstance(disconnectUserTaskInstance); + } + + @Test + public void testSuccessfulFindById() { + Optional result = Optional.of(TestUtils.createUserTaskInstanceEntity()); + + when(userTaskInstanceRepository.findById(any())).thenReturn(result); + + jpaUserTaskInstances.findById("1234"); + + verify(userTaskInstanceEntityMapper, times(1)).mapTaskEntityToInstance(any()); + verify(reconnectUserTaskInstance, times(1)).apply(any()); + } + + @Test + public void testUnSuccessfulFindById() { + when(userTaskInstanceRepository.findById(any())).thenReturn(Optional.empty()); + + jpaUserTaskInstances.findById("1234"); + + verify(userTaskInstanceEntityMapper, never()).mapTaskEntityToInstance(any()); + verify(reconnectUserTaskInstance, never()).apply(any()); + } + + @Test + public void testSuccessfulExists() { + Optional result = Optional.of(TestUtils.createUserTaskInstanceEntity()); + + when(userTaskInstanceRepository.findById(any())).thenReturn(result); + + Assertions.assertThat(jpaUserTaskInstances.exists("1234")) + .isTrue(); + + verify(userTaskInstanceEntityMapper, never()).mapTaskEntityToInstance(any()); + verify(reconnectUserTaskInstance, never()).apply(any()); + } + + @Test + public void testUnSuccessfulExists() { + when(userTaskInstanceRepository.findById(any())).thenReturn(Optional.empty()); + + Assertions.assertThat(jpaUserTaskInstances.exists("1234")) + .isFalse(); + + verify(userTaskInstanceEntityMapper, never()).mapTaskEntityToInstance(any()); + verify(reconnectUserTaskInstance, never()).apply(any()); + } + + @Test + public void testSuccessfulFindByIdentity() { + List result = List.of(TestUtils.createUserTaskInstanceEntity(), TestUtils.createUserTaskInstanceEntity()); + + when(userTaskInstanceRepository.findByIdentity(any())).thenReturn(result); + + List instances = jpaUserTaskInstances.findByIdentity(IdentityProviders.of("user", "group")); + + Assertions.assertThat(instances) + .hasSize(2); + + verify(userTaskInstanceEntityMapper, times(2)).mapTaskEntityToInstance(any()); + verify(reconnectUserTaskInstance, times(2)).apply(any()); + + } + + @Test + public void testUnSuccessfulFindByIdentity() { + when(userTaskInstanceRepository.findByIdentity(any())).thenReturn(List.of()); + + List instances = jpaUserTaskInstances.findByIdentity(IdentityProviders.of("user", "group")); + + Assertions.assertThat(instances) + .isEmpty(); + + verify(userTaskInstanceEntityMapper, never()).mapTaskEntityToInstance(any()); + verify(reconnectUserTaskInstance, never()).apply(any()); + } + + @Test + public void testSuccessfulCreate() { + when(userTaskInstanceRepository.findById(any())).thenReturn(Optional.empty()); + + jpaUserTaskInstances.create(TestUtils.createUserTaskInstance()); + + verify(userTaskInstanceRepository, times(1)).persist(any()); + verify(userTaskInstanceEntityMapper, times(1)).mapTaskInstanceToEntity(any(), any()); + verify(reconnectUserTaskInstance, times(1)).apply(any()); + } + + @Test + public void testUnSuccessfulCreate() { + Optional result = Optional.of(TestUtils.createUserTaskInstanceEntity()); + when(userTaskInstanceRepository.findById(any())).thenReturn(result); + + Assertions.assertThatThrownBy(() -> { + jpaUserTaskInstances.create(TestUtils.createUserTaskInstance()); + }).hasMessageContaining("Task Already exists."); + + verify(userTaskInstanceRepository, never()).persist(any()); + verify(userTaskInstanceEntityMapper, never()).mapTaskInstanceToEntity(any(), any()); + verify(reconnectUserTaskInstance, never()).apply(any()); + } + + @Test + public void testSuccessfulUpdate() { + Optional result = Optional.of(TestUtils.createUserTaskInstanceEntity()); + when(userTaskInstanceRepository.findById(any())).thenReturn(result); + + jpaUserTaskInstances.update(TestUtils.createUserTaskInstance()); + + verify(userTaskInstanceRepository, times(1)).update(any()); + verify(userTaskInstanceEntityMapper, times(1)).mapTaskInstanceToEntity(any(), any()); + } + + @Test + public void testUnSuccessfulUpdate() { + when(userTaskInstanceRepository.findById(any())).thenReturn(Optional.empty()); + + Assertions.assertThatThrownBy(() -> { + jpaUserTaskInstances.update(TestUtils.createUserTaskInstance()); + }).hasMessageContaining("Could not find userTaskInstance with id "); + + verify(userTaskInstanceRepository, never()).persist(any()); + verify(userTaskInstanceEntityMapper, never()).mapTaskInstanceToEntity(any(), any()); + } + + @Test + public void testSuccessfulRemove() { + Optional result = Optional.of(TestUtils.createUserTaskInstanceEntity()); + when(userTaskInstanceRepository.findById(any())).thenReturn(result); + + jpaUserTaskInstances.remove(TestUtils.createUserTaskInstance()); + + verify(userTaskInstanceRepository, times(1)).remove(any()); + verify(disconnectUserTaskInstance, times(1)).apply(any()); + } + + @Test + public void testUnSuccessfulRemove() { + when(userTaskInstanceRepository.findById(any())).thenReturn(Optional.empty()); + + Assertions.assertThatThrownBy(() -> { + jpaUserTaskInstances.remove(TestUtils.createUserTaskInstance()); + }).hasMessageContaining("Could not remove userTaskInstance with id"); + + verify(userTaskInstanceRepository, never()).persist(any()); + verify(disconnectUserTaskInstance, never()).apply(any()); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/AttachmentsEntityMapperTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/AttachmentsEntityMapperTest.java new file mode 100644 index 00000000000..cafdb8e166b --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/AttachmentsEntityMapperTest.java @@ -0,0 +1,135 @@ +/* + * 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.usertask.jpa.mapper; + +import java.net.URI; +import java.util.Date; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.AttachmentEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.AttachmentRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.model.Attachment; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class AttachmentsEntityMapperTest { + + @Mock + private AttachmentRepository repository; + private AttachmentsEntityMapper mapper; + + @BeforeEach + public void setup() { + mapper = new AttachmentsEntityMapper(repository); + } + + @Test + public void testMapAttachmentsFromInstanceToEntity() { + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + Attachment attachment = new Attachment("1", "John"); + attachment.setName("attachment 1"); + attachment.setContent(URI.create("http://localhost:8080/my-attachment.txt")); + attachment.setUpdatedAt(new Date()); + + Attachment attachment2 = new Attachment("2", "Ned"); + attachment2.setName("attachment 2"); + attachment2.setContent(URI.create("http://localhost:8080/my-attachment2.txt")); + attachment2.setUpdatedAt(new Date()); + + instance.addAttachment(attachment); + instance.addAttachment(attachment2); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getAttachments()) + .hasSize(2); + verify(repository, never()) + .remove(any()); + TestUtils.assertUserTaskEntityAttachments(entity.getAttachments(), instance.getAttachments()); + + instance.removeAttachment(attachment); + mapper.mapInstanceToEntity(instance, entity); + + verify(repository, times(1)) + .remove(any()); + Assertions.assertThat(entity.getAttachments()) + .hasSize(1); + TestUtils.assertUserTaskEntityAttachments(entity.getAttachments(), instance.getAttachments()); + + instance.removeAttachment(attachment2); + mapper.mapInstanceToEntity(instance, entity); + + verify(repository, times(2)) + .remove(any()); + Assertions.assertThat(entity.getAttachments()) + .hasSize(0); + } + + @Test + public void testMapAttachmentsFromEntityToInstance() { + + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + + AttachmentEntity attachment = new AttachmentEntity(); + attachment.setId("1"); + attachment.setUpdatedBy("John"); + attachment.setName("attachment 1"); + attachment.setUrl("http://localhost:8080/my-attachment.txt"); + attachment.setUpdatedAt(new Date()); + + AttachmentEntity attachment2 = new AttachmentEntity(); + attachment2.setId("2"); + attachment2.setUpdatedBy("Ned"); + attachment2.setName("attachment 2"); + attachment2.setUrl("http://localhost:8080/my-attachment_2.txt"); + attachment2.setUpdatedAt(new Date()); + + entity.addAttachment(attachment); + entity.addAttachment(attachment2); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getAttachments()) + .hasSize(2); + verify(repository, never()) + .remove(any()); + TestUtils.assertUserTaskInstanceAttachments(instance.getAttachments(), entity.getAttachments()); + + entity.removeAttachment(attachment); + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(entity.getAttachments()) + .hasSize(1); + TestUtils.assertUserTaskInstanceAttachments(instance.getAttachments(), entity.getAttachments()); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/CommentsEntityMapperTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/CommentsEntityMapperTest.java new file mode 100644 index 00000000000..62477c2d7ab --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/CommentsEntityMapperTest.java @@ -0,0 +1,145 @@ +/* + * 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.usertask.jpa.mapper; + +import java.util.Date; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.CommentEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.CommentRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.model.Comment; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class CommentsEntityMapperTest { + + @Mock + private CommentRepository repository; + private CommentsEntityMapper mapper; + + @BeforeEach + public void setup() { + mapper = new CommentsEntityMapper(repository); + } + + @Test + public void testMapCommentsFromInstanceToEntity() { + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + Comment comment = new Comment("1", "John"); + comment.setContent("This is comment 1"); + comment.setUpdatedAt(new Date()); + + Comment comment2 = new Comment("2", "Ned"); + comment2.setContent("This is comment 2"); + comment2.setUpdatedAt(new Date()); + + instance.addComment(comment); + instance.addComment(comment2); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getComments()) + .hasSize(2); + verify(repository, never()) + .remove(any()); + + TestUtils.assertUserTaskEntityComments(entity.getComments(), instance.getComments()); + + instance.removeComment(comment); + mapper.mapInstanceToEntity(instance, entity); + + verify(repository, times(1)) + .remove(any()); + Assertions.assertThat(entity.getComments()) + .hasSize(1); + TestUtils.assertUserTaskEntityComments(entity.getComments(), instance.getComments()); + + instance.removeComment(comment2); + mapper.mapInstanceToEntity(instance, entity); + + verify(repository, times(2)) + .remove(any()); + Assertions.assertThat(entity.getComments()) + .hasSize(0); + } + + @Test + public void testMapCommentsFromEntityToInstance() { + + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + + CommentEntity comment = new CommentEntity(); + comment.setId("1"); + comment.setUpdatedBy("John"); + comment.setComment("This is comment 1"); + comment.setUpdatedAt(new Date()); + + CommentEntity comment2 = new CommentEntity(); + comment2.setId("2"); + comment2.setUpdatedBy("Ned"); + comment2.setComment("This is comment 2"); + comment2.setUpdatedAt(new Date()); + + entity.addComment(comment); + entity.addComment(comment2); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getComments()) + .hasSize(2); + verify(repository, never()) + .remove(any()); + + TestUtils.assertUserTaskInstanceComments(instance.getComments(), entity.getComments()); + + entity.removeComment(comment); + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(entity.getComments()) + .hasSize(1); + TestUtils.assertUserTaskInstanceComments(instance.getComments(), entity.getComments()); + + entity.removeComment(comment); + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(entity.getComments()) + .hasSize(1); + TestUtils.assertUserTaskInstanceComments(instance.getComments(), entity.getComments()); + + entity.removeComment(comment2); + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(entity.getComments()) + .hasSize(0); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskInputsEntityMapperTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskInputsEntityMapperTest.java new file mode 100644 index 00000000000..1aaeed39d30 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskInputsEntityMapperTest.java @@ -0,0 +1,144 @@ +/* + * 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.usertask.jpa.mapper; + +import java.nio.charset.StandardCharsets; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.TaskInputEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.TaskInputRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class TaskInputsEntityMapperTest { + + @Mock + private TaskInputRepository repository; + private TaskInputsEntityMapper mapper; + + @BeforeEach + public void setup() { + mapper = new TaskInputsEntityMapper(repository); + } + + @Test + public void testMapInputsFromInstanceToEntity() { + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getInputs()) + .hasSize(8); + verify(repository, never()) + .remove(any()); + TestUtils.assertUserTaskEntityInputs(entity, instance); + + instance.getInputs().remove("in_string"); + instance.getInputs().remove("in_integer"); + instance.getInputs().remove("in_null"); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getInputs()) + .hasSize(5); + verify(repository, times(3)) + .remove(any()); + + TestUtils.assertUserTaskEntityInputs(entity, instance); + + instance.getInputs().clear(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getInputs()) + .hasSize(0); + verify(repository, times(8)) + .remove(any()); + } + + @Test + public void testMapInputsFromEntityToInstance() { + final String stringValue = "This is the input value"; + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + TaskInputEntity input = new TaskInputEntity(); + input.setName("in_string"); + input.setValue(stringValue.getBytes(StandardCharsets.UTF_8)); + + entity.addInput(input); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getInputs()) + .hasSize(1); + + TestUtils.assertUserTaskInstanceInputs(instance, entity); + + entity.getInputs().clear(); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getInputs()) + .hasSize(0); + } + + @Test + public void testMappingRoundCircle() { + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getInputs()) + .hasSize(8); + verify(repository, never()) + .remove(any()); + + TestUtils.assertUserTaskEntityInputs(entity, instance); + + DefaultUserTaskInstance instance2 = new DefaultUserTaskInstance(); + + mapper.mapEntityToInstance(entity, instance2); + + Assertions.assertThat(instance2.getInputs()) + .hasSize(8); + + TestUtils.assertUserTaskInstanceInputs(instance2, entity); + + Assertions.assertThat(instance2.getInputs()) + .usingRecursiveComparison() + .isEqualTo(instance.getInputs()); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskMetadataEntityMapperTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskMetadataEntityMapperTest.java new file mode 100644 index 00000000000..1e6d18de1fd --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskMetadataEntityMapperTest.java @@ -0,0 +1,145 @@ +/* + * 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.usertask.jpa.mapper; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.TaskMetadataEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.TaskMetadataRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class TaskMetadataEntityMapperTest { + + @Mock + private TaskMetadataRepository repository; + private TaskMetadataEntityMapper mapper; + + @BeforeEach + public void setup() { + mapper = new TaskMetadataEntityMapper(repository); + } + + @Test + public void testMapMetadataFromInstanceToEntity() { + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getMetadata()) + .hasSize(6); + verify(repository, never()) + .remove(any()); + TestUtils.assertUserTaskEntityMetadata(entity, instance); + + instance.getMetadata().remove("ProcessId"); + instance.getMetadata().remove("ProcessType"); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getMetadata()) + .hasSize(4); + verify(repository, times(2)) + .remove(any()); + + TestUtils.assertUserTaskEntityMetadata(entity, instance); + + instance.getMetadata().clear(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getMetadata()) + .hasSize(0); + verify(repository, times(6)) + .remove(any()); + } + + @Test + public void testMapMetadataFromEntityToInstance() { + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + TaskMetadataEntity metadata = new TaskMetadataEntity(); + metadata.setName("ProcessId"); + metadata.setValue("1234"); + + TaskMetadataEntity metadata2 = new TaskMetadataEntity(); + metadata2.setName("CustomMetadata"); + metadata2.setValue("This is the metadata value"); + + entity.addMetadata(metadata); + entity.addMetadata(metadata2); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getMetadata()) + .hasSize(2); + + TestUtils.assertUserTaskInstanceMetadata(instance, entity); + + entity.getMetadata().clear(); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getMetadata()) + .hasSize(0); + } + + @Test + public void testFullMappingCircle() { + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getMetadata()) + .hasSize(6); + verify(repository, never()) + .remove(any()); + + TestUtils.assertUserTaskEntityMetadata(entity, instance); + + DefaultUserTaskInstance instance2 = new DefaultUserTaskInstance(); + + mapper.mapEntityToInstance(entity, instance2); + + Assertions.assertThat(instance2.getMetadata()) + .hasSize(6); + + TestUtils.assertUserTaskInstanceMetadata(instance2, entity); + + Assertions.assertThat(instance2.getMetadata()) + .usingRecursiveComparison() + .isEqualTo(instance.getMetadata()); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskOutputsEntityMapperTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskOutputsEntityMapperTest.java new file mode 100644 index 00000000000..52da167c9d1 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/TaskOutputsEntityMapperTest.java @@ -0,0 +1,143 @@ +/* + * 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.usertask.jpa.mapper; + +import java.nio.charset.StandardCharsets; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.TaskOutputEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.repository.TaskOutputRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class TaskOutputsEntityMapperTest { + + @Mock + private TaskOutputRepository repository; + private TaskOutputsEntityMapper mapper; + + @BeforeEach + public void setup() { + mapper = new TaskOutputsEntityMapper(repository); + } + + @Test + public void testMapOutputsFromInstanceToEntity() { + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getOutputs()) + .hasSize(8); + verify(repository, never()) + .remove(any()); + TestUtils.assertUserTaskEntityOutputs(entity, instance); + + instance.getOutputs().remove("out_string"); + instance.getOutputs().remove("out_integer"); + instance.getOutputs().remove("out_null"); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getOutputs()) + .hasSize(5); + verify(repository, times(3)) + .remove(any()); + + TestUtils.assertUserTaskEntityOutputs(entity, instance); + + instance.getOutputs().clear(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getOutputs()) + .hasSize(0); + verify(repository, times(8)) + .remove(any()); + } + + @Test + public void testMapOutputsFromEntityToInstance() { + final String stringValue = "This is the output value"; + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + TaskOutputEntity output = new TaskOutputEntity(); + output.setName("out_string"); + output.setValue(stringValue.getBytes(StandardCharsets.UTF_8)); + + entity.addOutput(output); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getOutputs()) + .hasSize(1); + + TestUtils.assertUserTaskInstanceOutputs(instance, entity); + + entity.getOutputs().clear(); + + mapper.mapEntityToInstance(entity, instance); + + Assertions.assertThat(instance.getOutputs()) + .hasSize(0); + } + + @Test + public void testMappingRoundCircle() { + + UserTaskInstance instance = TestUtils.createUserTaskInstance(); + UserTaskInstanceEntity entity = new UserTaskInstanceEntity(); + + mapper.mapInstanceToEntity(instance, entity); + + Assertions.assertThat(entity.getOutputs()) + .hasSize(8); + verify(repository, never()) + .remove(any()); + TestUtils.assertUserTaskEntityOutputs(entity, instance); + + DefaultUserTaskInstance instance2 = new DefaultUserTaskInstance(); + + mapper.mapEntityToInstance(entity, instance2); + + Assertions.assertThat(instance2.getOutputs()) + .hasSize(8); + + TestUtils.assertUserTaskInstanceOutputs(instance2, entity); + + Assertions.assertThat(instance2.getOutputs()) + .usingRecursiveComparison() + .isEqualTo(instance.getOutputs()); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/UserTaskInstanceEntityMapperTest.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/UserTaskInstanceEntityMapperTest.java new file mode 100644 index 00000000000..3b49d9b445d --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/UserTaskInstanceEntityMapperTest.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.jbpm.usertask.jpa.mapper; + +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.kie.kogito.usertask.UserTaskInstance; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserTaskInstanceEntityMapperTest { + + @Mock + private AttachmentsEntityMapper attachmentsEntityMapper; + @Mock + private CommentsEntityMapper commentsEntityMapper; + @Mock + private TaskMetadataEntityMapper metadataEntityMapper; + @Mock + private TaskInputsEntityMapper inputsEntityMapper; + @Mock + private TaskOutputsEntityMapper outputsEntityMapper; + + private UserTaskInstanceEntityMapper userTaskInstanceEntityMapper; + + @BeforeEach + public void setUp() { + this.userTaskInstanceEntityMapper = new UserTaskInstanceEntityMapper(attachmentsEntityMapper, commentsEntityMapper, metadataEntityMapper, inputsEntityMapper, outputsEntityMapper); + } + + @Test + public void testUserTaskInstanceToUserTaskEntityMapper() { + UserTaskInstance userTaskInstance = TestUtils.createUserTaskInstance(); + + UserTaskInstanceEntity userTaskInstanceEntity = new UserTaskInstanceEntity(); + + userTaskInstanceEntityMapper.mapTaskInstanceToEntity(userTaskInstance, userTaskInstanceEntity); + + verify(attachmentsEntityMapper, times(1)) + .mapInstanceToEntity(same(userTaskInstance), same(userTaskInstanceEntity)); + verify(commentsEntityMapper, times(1)) + .mapInstanceToEntity(same(userTaskInstance), same(userTaskInstanceEntity)); + verify(metadataEntityMapper, times(1)) + .mapInstanceToEntity(same(userTaskInstance), same(userTaskInstanceEntity)); + verify(inputsEntityMapper, times(1)) + .mapInstanceToEntity(same(userTaskInstance), same(userTaskInstanceEntity)); + verify(outputsEntityMapper, times(1)) + .mapInstanceToEntity(same(userTaskInstance), same(userTaskInstanceEntity)); + + TestUtils.assertUserTaskEntityData(userTaskInstanceEntity, userTaskInstance); + TestUtils.assertUserTaskEntityPotentialUserAndGroups(userTaskInstanceEntity, userTaskInstance); + TestUtils.assertUserTaskEntityAdminUserAndGroups(userTaskInstanceEntity, userTaskInstance); + TestUtils.assertUserTaskEntityExcludedUsers(userTaskInstanceEntity, userTaskInstance); + } + + @Test + public void testUserTaskEntityToUserTaskInstanceMapper() { + UserTaskInstanceEntity userTaskInstanceEntity = TestUtils.createUserTaskInstanceEntity(); + + UserTaskInstance userTaskInstance = userTaskInstanceEntityMapper.mapTaskEntityToInstance(userTaskInstanceEntity); + + verify(attachmentsEntityMapper, times(1)) + .mapEntityToInstance(same(userTaskInstanceEntity), same(userTaskInstance)); + verify(commentsEntityMapper, times(1)) + .mapEntityToInstance(same(userTaskInstanceEntity), same(userTaskInstance)); + verify(metadataEntityMapper, times(1)) + .mapEntityToInstance(same(userTaskInstanceEntity), same(userTaskInstance)); + verify(inputsEntityMapper, times(1)) + .mapEntityToInstance(same(userTaskInstanceEntity), same(userTaskInstance)); + verify(outputsEntityMapper, times(1)) + .mapEntityToInstance(same(userTaskInstanceEntity), same(userTaskInstance)); + + TestUtils.assertUserTaskInstanceData(userTaskInstance, userTaskInstanceEntity); + TestUtils.assertUserTaskInstancePotentialUserAndGroups(userTaskInstance, userTaskInstanceEntity); + TestUtils.assertUserTaskInstanceAdminUserAndGroups(userTaskInstance, userTaskInstanceEntity); + TestUtils.assertUserTaskInstanceExcludedUsers(userTaskInstance, userTaskInstanceEntity); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/models/Person.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/models/Person.java new file mode 100644 index 00000000000..3c1d911f1e6 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/models/Person.java @@ -0,0 +1,76 @@ +/* + * 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.usertask.jpa.mapper.models; + +import java.util.Objects; + +public class Person { + String name; + String lastName; + int age; + + public Person() { + } + + public Person(String name, String lastName, int age) { + this.name = name; + this.lastName = lastName; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Person person = (Person) o; + return age == person.age && Objects.equals(name, person.name) && Objects.equals(lastName, person.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(name, lastName, age); + } +} diff --git a/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/utils/TestUtils.java b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/utils/TestUtils.java new file mode 100644 index 00000000000..b1b4373f369 --- /dev/null +++ b/addons/common/jbpm-usertask-storage-jpa/src/test/java/org/jbpm/usertask/jpa/mapper/utils/TestUtils.java @@ -0,0 +1,317 @@ +/* + * 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.usertask.jpa.mapper.utils; + +import java.util.*; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.mapper.models.Person; +import org.jbpm.usertask.jpa.model.AttachmentEntity; +import org.jbpm.usertask.jpa.model.CommentEntity; +import org.jbpm.usertask.jpa.model.TaskDataEntity; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.kie.kogito.usertask.lifecycle.UserTaskState; +import org.kie.kogito.usertask.model.Attachment; +import org.kie.kogito.usertask.model.Comment; + +public class TestUtils { + + private TestUtils() { + } + + public static void assertUserTaskEntityData(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + Assertions.assertThat(userTaskInstanceEntity) + .hasFieldOrPropertyWithValue("id", userTaskInstance.getId()) + .hasFieldOrPropertyWithValue("userTaskId", userTaskInstance.getUserTaskId()) + .hasFieldOrPropertyWithValue("taskName", userTaskInstance.getTaskName()) + .hasFieldOrPropertyWithValue("taskDescription", userTaskInstance.getTaskDescription()) + .hasFieldOrPropertyWithValue("taskPriority", userTaskInstance.getTaskPriority()) + .hasFieldOrPropertyWithValue("status", userTaskInstance.getStatus().getName()) + .hasFieldOrPropertyWithValue("terminationType", userTaskInstance.getStatus().getTerminate().toString()) + .hasFieldOrPropertyWithValue("externalReferenceId", userTaskInstance.getExternalReferenceId()) + .hasFieldOrPropertyWithValue("actualOwner", userTaskInstance.getActualOwner()); + } + + public static void assertUserTaskInstanceData(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + UserTaskState.TerminationType terminationType = + Objects.isNull(userTaskInstanceEntity.getTerminationType()) ? null : UserTaskState.TerminationType.valueOf(userTaskInstanceEntity.getTerminationType()); + UserTaskState state = UserTaskState.of(userTaskInstanceEntity.getStatus(), terminationType); + + Assertions.assertThat(userTaskInstance) + .hasFieldOrPropertyWithValue("id", userTaskInstanceEntity.getId()) + .hasFieldOrPropertyWithValue("userTaskId", userTaskInstanceEntity.getUserTaskId()) + .hasFieldOrPropertyWithValue("taskName", userTaskInstanceEntity.getTaskName()) + .hasFieldOrPropertyWithValue("taskDescription", userTaskInstanceEntity.getTaskDescription()) + .hasFieldOrPropertyWithValue("taskPriority", userTaskInstanceEntity.getTaskPriority()) + .hasFieldOrPropertyWithValue("status", state) + .hasFieldOrPropertyWithValue("externalReferenceId", userTaskInstanceEntity.getExternalReferenceId()) + .hasFieldOrPropertyWithValue("actualOwner", userTaskInstanceEntity.getActualOwner()); + } + + public static void assertUserTaskEntityPotentialUserAndGroups(UserTaskInstanceEntity userTaskEntity, UserTaskInstance userTaskInstance) { + assertUserOrGroupsAssignments(userTaskEntity.getPotentialUsers(), userTaskInstance.getPotentialUsers()); + assertUserOrGroupsAssignments(userTaskEntity.getPotentialGroups(), userTaskInstance.getPotentialGroups()); + } + + public static void assertUserTaskEntityAdminUserAndGroups(UserTaskInstanceEntity userTaskEntity, UserTaskInstance userTaskInstance) { + assertUserOrGroupsAssignments(userTaskEntity.getAdminUsers(), userTaskInstance.getAdminUsers()); + assertUserOrGroupsAssignments(userTaskEntity.getAdminGroups(), userTaskInstance.getAdminGroups()); + } + + public static void assertUserTaskEntityExcludedUsers(UserTaskInstanceEntity userTaskEntity, UserTaskInstance userTaskInstance) { + assertUserOrGroupsAssignments(userTaskEntity.getExcludedUsers(), userTaskInstance.getExcludedUsers()); + } + + public static void assertUserTaskInstancePotentialUserAndGroups(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskEntity) { + assertUserOrGroupsAssignments(userTaskInstance.getPotentialUsers(), userTaskEntity.getPotentialUsers()); + assertUserOrGroupsAssignments(userTaskInstance.getPotentialGroups(), userTaskEntity.getPotentialGroups()); + } + + public static void assertUserTaskInstanceAdminUserAndGroups(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskEntity) { + assertUserOrGroupsAssignments(userTaskInstance.getAdminUsers(), userTaskEntity.getAdminUsers()); + assertUserOrGroupsAssignments(userTaskInstance.getAdminGroups(), userTaskEntity.getAdminGroups()); + } + + public static void assertUserTaskInstanceExcludedUsers(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskEntity) { + assertUserOrGroupsAssignments(userTaskInstance.getExcludedUsers(), userTaskEntity.getExcludedUsers()); + } + + private static void assertUserOrGroupsAssignments(Collection entityAssignments, Collection instanceAssignments) { + Assertions.assertThat(entityAssignments) + .hasSize(instanceAssignments.size()) + .containsExactlyInAnyOrder(instanceAssignments.toArray(new String[0])); + } + + public static void assertUserTaskEntityComments(Collection entityComments, Collection instanceComments) { + Assertions.assertThat(entityComments) + .hasSize(instanceComments.size()); + + entityComments.forEach(entityComment -> { + Optional optional = instanceComments.stream() + .filter(instanceComment -> instanceComment.getId().equals(entityComment.getId())) + .findFirst(); + + Assertions.assertThat(optional) + .isPresent(); + + Comment instanceComment = optional.get(); + + Assertions.assertThat(entityComment) + .hasFieldOrPropertyWithValue("id", instanceComment.getId()) + .hasFieldOrPropertyWithValue("comment", instanceComment.getContent()) + .hasFieldOrPropertyWithValue("updatedBy", instanceComment.getUpdatedBy()) + .matches(entity -> entity.getUpdatedAt().getTime() == instanceComment.getUpdatedAt().getTime()); + }); + } + + public static void assertUserTaskInstanceComments(Collection instanceComments, Collection entityComments) { + Assertions.assertThat(instanceComments) + .hasSize(instanceComments.size()); + + instanceComments.forEach(instanceComment -> { + Optional optional = entityComments.stream() + .filter(entityComment -> entityComment.getId().equals(instanceComment.getId())) + .findFirst(); + + Assertions.assertThat(optional) + .isPresent(); + + CommentEntity entityComment = optional.get(); + + Assertions.assertThat(instanceComment) + .hasFieldOrPropertyWithValue("id", entityComment.getId()) + .hasFieldOrPropertyWithValue("content", entityComment.getComment()) + .hasFieldOrPropertyWithValue("updatedBy", entityComment.getUpdatedBy()) + .matches(entity -> entity.getUpdatedAt().getTime() == entityComment.getUpdatedAt().getTime()); + }); + } + + public static void assertUserTaskEntityAttachments(Collection entityAttachments, Collection instanceAttachments) { + Assertions.assertThat(entityAttachments) + .hasSize(instanceAttachments.size()); + + entityAttachments.forEach(entityAttachment -> { + Optional optional = instanceAttachments.stream() + .filter(instanceAttachment -> instanceAttachment.getId().equals(entityAttachment.getId())) + .findFirst(); + + Assertions.assertThat(optional) + .isPresent(); + + Attachment instanceAttachment = optional.get(); + + Assertions.assertThat(entityAttachment) + .hasFieldOrPropertyWithValue("id", instanceAttachment.getId()) + .hasFieldOrPropertyWithValue("name", instanceAttachment.getName()) + .hasFieldOrPropertyWithValue("updatedBy", instanceAttachment.getUpdatedBy()) + .matches(entity -> entity.getUpdatedAt().getTime() == instanceAttachment.getUpdatedAt().getTime()) + .hasFieldOrPropertyWithValue("url", instanceAttachment.getContent().toString()); + }); + } + + public static void assertUserTaskInstanceAttachments(Collection instanceAttachments, Collection entityAttachments) { + Assertions.assertThat(instanceAttachments) + .hasSize(instanceAttachments.size()); + + instanceAttachments.forEach(instanceAttachment -> { + Optional optional = entityAttachments.stream() + .filter(entityAttachment -> entityAttachment.getId().equals(instanceAttachment.getId())) + .findFirst(); + + Assertions.assertThat(optional) + .isPresent(); + + AttachmentEntity entityAttachment = optional.get(); + + Assertions.assertThat(instanceAttachment) + .hasFieldOrPropertyWithValue("id", entityAttachment.getId()) + .hasFieldOrPropertyWithValue("name", entityAttachment.getName()) + .hasFieldOrPropertyWithValue("updatedBy", entityAttachment.getUpdatedBy()) + .matches(entity -> entity.getUpdatedAt().getTime() == entityAttachment.getUpdatedAt().getTime()) + .matches(entity -> entity.getContent().toString().equals(entityAttachment.getUrl())); + }); + } + + public static void assertUserTaskEntityInputs(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + assertUserTaskEntityMapData(userTaskInstanceEntity.getInputs(), userTaskInstance.getInputs()); + } + + public static void assertUserTaskEntityOutputs(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + assertUserTaskEntityMapData(userTaskInstanceEntity.getOutputs(), userTaskInstance.getOutputs()); + } + + public static void assertUserTaskEntityMetadata(UserTaskInstanceEntity userTaskInstanceEntity, UserTaskInstance userTaskInstance) { + assertUserTaskEntityMapData(userTaskInstanceEntity.getMetadata(), userTaskInstance.getMetadata()); + } + + private static void assertUserTaskEntityMapData(Collection entityData, Map instanceData) { + Assertions.assertThat(entityData.size()) + .isEqualTo(instanceData.size()); + + entityData.stream().forEach(entity -> { + Object value = instanceData.get(entity.getName()); + Assertions.assertThat(entity) + .isNotNull() + .matches(e -> instanceData.containsKey(e.getName())) + .matches(e -> Objects.isNull(e.getValue()) ? Objects.isNull(value) : e.getJavaType().equals(value.getClass().getName())); + }); + } + + public static void assertUserTaskInstanceInputs(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + assertUserTaskInstanceMapData(userTaskInstance.getInputs(), userTaskInstanceEntity.getInputs()); + } + + public static void assertUserTaskInstanceOutputs(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + assertUserTaskInstanceMapData(userTaskInstance.getOutputs(), userTaskInstanceEntity.getOutputs()); + } + + public static void assertUserTaskInstanceMetadata(UserTaskInstance userTaskInstance, UserTaskInstanceEntity userTaskInstanceEntity) { + assertUserTaskInstanceMapData(userTaskInstance.getMetadata(), userTaskInstanceEntity.getMetadata()); + } + + private static void assertUserTaskInstanceMapData(Map instanceData, Collection entityData) { + Assertions.assertThat(instanceData.size()) + .isEqualTo(entityData.size()); + + instanceData.forEach((key, value) -> { + Optional optional = entityData.stream().filter(data -> data.getName().equals(key)).findFirst(); + + Assertions.assertThat(optional) + .isPresent(); + + if (Objects.nonNull(value)) { + TaskDataEntity data = optional.get(); + Assertions.assertThat(value.getClass().getName()) + .isEqualTo(data.getJavaType()); + } + }); + } + + public static DefaultUserTaskInstance createUserTaskInstance() { + DefaultUserTaskInstance instance = new DefaultUserTaskInstance(); + instance.setId(UUID.randomUUID().toString()); + instance.setUserTaskId("user-task-id"); + instance.setTaskName("test-task"); + instance.setTaskDescription("this is a test task description"); + instance.setTaskPriority("1"); + instance.setStatus(UserTaskState.of("Complete", UserTaskState.TerminationType.COMPLETED)); + + instance.setActualOwner("Homer"); + instance.setPotentialUsers(Set.of("Bart", "Liza")); + instance.setPotentialGroups(Set.of("Simpson", "Family")); + instance.setAdminUsers(Set.of("Seymour")); + instance.setAdminGroups(Set.of("Administrators", "Managers")); + instance.setExcludedUsers(Set.of("Ned", "Bart")); + + instance.setExternalReferenceId("external-reference-id"); + + instance.setMetadata("ProcessId", "process-id"); + instance.setMetadata("ProcessType", "BPMN"); + instance.setMetadata("ProcessVersion", "1.0.0"); + instance.setMetadata("boolean", true); + instance.setMetadata("integer", 0); + instance.setMetadata("null", 0); + + instance.setInput("in_string", "hello this is a string"); + instance.setInput("in_integer", 1); + instance.setInput("in_long", 1000L); + instance.setInput("in_float", 1.02f); + instance.setInput("in_boolean", true); + instance.setInput("in_date", new Date()); + instance.setInput("in_person", new Person("Ned", "Stark", 50)); + instance.setInput("in_null", null); + + instance.setOutput("out_string", "hello this is an output string"); + instance.setOutput("out_integer", 12); + instance.setOutput("out_long", 2000L); + instance.setOutput("out_float", 3.5f); + instance.setOutput("out_boolean", false); + instance.setOutput("out_date", new Date()); + instance.setOutput("out_person", new Person("Jon", "Snow", 17)); + instance.setOutput("out_null", null); + + return instance; + } + + public static UserTaskInstanceEntity createUserTaskInstanceEntity() { + UserTaskInstanceEntity instance = new UserTaskInstanceEntity(); + + instance.setId(UUID.randomUUID().toString()); + instance.setUserTaskId("user-task-id"); + instance.setTaskName("test-task"); + instance.setTaskDescription("this is a test task description"); + instance.setTaskPriority("1"); + instance.setStatus("Complete"); + instance.setTerminationType(UserTaskState.TerminationType.COMPLETED.name()); + + instance.setActualOwner("Homer"); + instance.setPotentialUsers(Set.of("Bart")); + instance.setPotentialGroups(Set.of("Simpson", "Family")); + instance.setAdminUsers(Set.of("Seymour")); + instance.setAdminGroups(Set.of("Administrators", "Managers")); + instance.setExcludedUsers(Set.of("Ned")); + + instance.setExternalReferenceId("external-reference-id"); + + return instance; + } +} diff --git a/addons/common/pom.xml b/addons/common/pom.xml index 1a12e57c0c9..fe7ccb1dcf6 100644 --- a/addons/common/pom.xml +++ b/addons/common/pom.xml @@ -55,6 +55,7 @@ task-management marshallers flyway + jbpm-usertask-storage-jpa diff --git a/api/kogito-api/src/main/java/org/kie/kogito/auth/IdentityProviders.java b/api/kogito-api/src/main/java/org/kie/kogito/auth/IdentityProviders.java index 2d1073893f7..8d560bc801f 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/auth/IdentityProviders.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/auth/IdentityProviders.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.List; public class IdentityProviders { @@ -52,8 +53,8 @@ public boolean hasRole(String role) { } - public static IdentityProvider of(String name) { - return new DefaultIdentityProvider(name, Collections.emptyList()); + public static IdentityProvider of(String name, String... roles) { + return new DefaultIdentityProvider(name, List.of(roles)); } public static IdentityProvider of(String name, Collection roles) { diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java index 9e101eb9d4b..e28e23befed 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java @@ -39,7 +39,7 @@ public interface UserTaskInstance { boolean hasActualOwner(); - void setActuaOwner(String actualOwner); + void setActualOwner(String actualOwner); String getActualOwner(); diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java index 7f294b15fed..8372c4e2747 100644 --- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java +++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java @@ -40,6 +40,6 @@ public interface UserTaskInstances { UserTaskInstance update(UserTaskInstance userTaskInstance); - UserTaskInstance remove(String userTaskInstanceId); + UserTaskInstance remove(UserTaskInstance userTaskInstanceId); } diff --git a/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java b/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java index 71d34053787..cf30b7ed2bf 100644 --- a/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java +++ b/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java @@ -73,10 +73,14 @@ public Optional activateWorkItemHandler(KogitoWorkItemManage UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID)); DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTask.createInstance(); + + instance.setExternalReferenceId(workItem.getStringId()); + + userTask.instances().create(instance); + instance.setTaskName((String) workItem.getParameter(TASK_NAME)); instance.setTaskDescription((String) workItem.getParameter(DESCRIPTION)); instance.setTaskPriority(priority != null ? priority.toString() : null); - instance.setExternalReferenceId(workItem.getStringId()); instance.setMetadata("ProcessId", workItem.getProcessInstance().getProcessId()); instance.setMetadata("ProcessType", workItem.getProcessInstance().getProcess().getType()); @@ -87,7 +91,6 @@ public Optional activateWorkItemHandler(KogitoWorkItemManage instance.setMetadata("RootProcessInstanceId", workItem.getProcessInstance().getRootProcessInstanceId()); instance.setMetadata("ParentProcessInstanceId", workItem.getProcessInstance().getParentProcessInstanceId()); - userTask.instances().create(instance); instance.fireInitialStateChange(); workItem.getParameters().entrySet().stream().filter(e -> !HumanTaskNode.TASK_PARAMETERS.contains(e.getKey())).forEach(e -> instance.setInput(e.getKey(), e.getValue())); @@ -109,6 +112,9 @@ public Optional activateWorkItemHandler(KogitoWorkItemManage @Override public Optional completeWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { + if (transition.data().containsKey("Notify")) { + return Optional.empty(); + } UserTasks userTasks = handler.getApplication().get(UserTasks.class); UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID)); userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> { @@ -122,6 +128,9 @@ public Optional completeWorkItemHandler(KogitoWorkItemManage @Override public Optional abortWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) { + if (transition.data().containsKey("Notify")) { + return Optional.empty(); + } UserTasks userTasks = handler.getApplication().get(UserTasks.class); UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID)); userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> { diff --git a/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java b/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java index 7d0bc70557a..116eb8716fd 100644 --- a/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java +++ b/jbpm/jbpm-usertask-workitem/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java @@ -59,6 +59,7 @@ public void onUserTaskState(UserTaskStateEvent event) { processes.processById(processId).instances().findById(processInstanceId).ifPresent(pi -> { Map data = new HashMap<>(event.getUserTaskInstance().getOutputs()); data.put("ActorId", event.getUserTaskInstance().getActualOwner()); + data.put("Notify", false); pi.completeWorkItem(event.getUserTaskInstance().getExternalReferenceId(), data); }); diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java index 68f85aceb3f..795c0f25e9c 100644 --- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java +++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java @@ -74,8 +74,9 @@ public UserTaskInstance createInstance() { instance.setPotentialUsers(getPotentialUsers()); instance.setPotentialGroups(getPotentialGroups()); instance.setAdminUsers(getAdminUsers()); - instance.setPotentialGroups(getPotentialGroups()); + instance.setAdminGroups(getAdminGroups()); instance.setExcludedUsers(getExcludedUsers()); + instance.setInstances(this.instances()); return instance; } diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java index fd6d3ce21c3..266e674887e 100644 --- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java +++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java @@ -18,15 +18,7 @@ */ package org.kie.kogito.usertask.impl; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import org.kie.kogito.auth.IdentityProvider; import org.kie.kogito.internal.usertask.event.KogitoUserTaskEventSupport; @@ -74,7 +66,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance { @JsonIgnore private KogitoUserTaskEventSupport userTaskEventSupport; @JsonIgnore - private UserTaskLifeCycle setUserTaskLifeCycle; + private UserTaskLifeCycle userTaskLifeCycle; public DefaultUserTaskInstance() { this.inputs = new HashMap<>(); @@ -94,7 +86,6 @@ public DefaultUserTaskInstance(UserTask userTask) { this(); this.id = UUID.randomUUID().toString(); this.userTask = userTask; - this.instances = userTask.instances(); } public void setUserTaskEventSupport(KogitoUserTaskEventSupport userTaskEventSupport) { @@ -102,7 +93,7 @@ public void setUserTaskEventSupport(KogitoUserTaskEventSupport userTaskEventSupp } public void setUserTaskLifeCycle(UserTaskLifeCycle userTaskLifeCycle) { - this.setUserTaskLifeCycle = userTaskLifeCycle; + this.userTaskLifeCycle = userTaskLifeCycle; } public void setInstances(UserTaskInstances instances) { @@ -142,7 +133,7 @@ public boolean hasActualOwner() { } @Override - public void setActuaOwner(String actualOwner) { + public void setActualOwner(String actualOwner) { this.actualOwner = actualOwner; if (this.userTaskEventSupport != null) { this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status, this.status); @@ -166,15 +157,14 @@ public void setExternalReferenceId(String externalReferenceId) { @Override public void transition(String transitionId, Map data, IdentityProvider identity) { - Optional next = Optional.of(this.setUserTaskLifeCycle.newTransitionToken(transitionId, this, data)); + Optional next = Optional.of(this.userTaskLifeCycle.newTransitionToken(transitionId, this, data)); while (next.isPresent()) { UserTaskTransitionToken transition = next.get(); - next = this.setUserTaskLifeCycle.transition(this, transition, identity); + next = this.userTaskLifeCycle.transition(this, transition, identity); this.status = transition.target(); - this.updatePersistenceOrRemove(); this.userTaskEventSupport.fireOneUserTaskStateChange(this, transition.source(), transition.target()); } - + this.updatePersistenceOrRemove(); } private void updatePersistence() { @@ -185,7 +175,7 @@ private void updatePersistence() { private void updatePersistenceOrRemove() { if (this.status.isTerminate()) { - this.instances.remove(this.id); + this.instances.remove(this); } else { this.instances.update(this); } @@ -205,7 +195,7 @@ public Map getInputs() { } public void setInputs(Map inputs) { - inputs.forEach(this::setInput); + this.inputs = inputs; } public Map getOutputs() { @@ -213,7 +203,7 @@ public Map getOutputs() { } public void setOutputs(Map outputs) { - outputs.forEach(this::setOutput); + this.outputs = outputs; } @Override @@ -451,8 +441,6 @@ public Attachment removeAttachment(Attachment attachment) { public void setAttachments(List attachments) { this.attachments = attachments; - updatePersistence(); - } /** @@ -509,7 +497,6 @@ public Comment removeComment(Comment comment) { public void setComments(List comments) { this.comments = comments; - updatePersistence(); } public void setMetadata(String key, Object value) { @@ -523,7 +510,6 @@ public Map getMetadata() { public void setMetadata(Map metadata) { this.metadata = metadata; - updatePersistence(); } @Override diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java index def2088da39..256144c4849 100644 --- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java +++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java @@ -161,14 +161,15 @@ public UserTaskInstance update(UserTaskInstance userTaskInstance) { } @Override - public UserTaskInstance remove(String userTaskInstanceId) { + public UserTaskInstance remove(UserTaskInstance userTaskInstance) { try { - if (!userTaskInstances.containsKey(userTaskInstanceId)) { + if (!userTaskInstances.containsKey(userTaskInstance.getId())) { return null; } - return disconnectUserTaskInstance.apply(mapper.readValue(userTaskInstances.remove(userTaskInstanceId), DefaultUserTaskInstance.class)); + userTaskInstances.remove(userTaskInstance.getId()); + return disconnectUserTaskInstance.apply(userTaskInstance); } catch (Exception e) { - LOG.error("during remove {}", userTaskInstanceId, e); + LOG.error("during remove {}", userTaskInstance, e); return null; } } diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java index a28a5accfde..6af8a612fcf 100644 --- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java +++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java @@ -127,9 +127,9 @@ public Optional activate(UserTaskInstance userTaskInsta public Optional claim(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) { if (userTaskInstance instanceof DefaultUserTaskInstance defaultUserTaskInstance) { if (token.data().containsKey(PARAMETER_USER)) { - defaultUserTaskInstance.setActuaOwner((String) token.data().get(PARAMETER_USER)); + defaultUserTaskInstance.setActualOwner((String) token.data().get(PARAMETER_USER)); } else { - defaultUserTaskInstance.setActuaOwner(identityProvider.getName()); + defaultUserTaskInstance.setActualOwner(identityProvider.getName()); } } return Optional.empty(); @@ -137,7 +137,7 @@ public Optional claim(UserTaskInstance userTaskInstance public Optional release(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) { if (userTaskInstance instanceof DefaultUserTaskInstance defaultUserTaskInstance) { - defaultUserTaskInstance.setActuaOwner(null); + defaultUserTaskInstance.setActualOwner(null); } return Optional.empty(); } diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java index f8cfd7733fc..56561c9ca51 100644 --- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java +++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java @@ -19,6 +19,7 @@ package org.kie.kogito.usertask.impl.lifecycle; import java.util.Map; +import java.util.Objects; import org.kie.kogito.usertask.lifecycle.UserTaskState; import org.kie.kogito.usertask.lifecycle.UserTaskTransitionToken; @@ -34,7 +35,7 @@ public DefaultUserTaskTransitionToken(String transition, UserTaskState source, U this.transition = transition; this.source = source; this.target = target; - this.data = data; + this.data = Objects.isNull(data) ? Map.of() : data; } @Override diff --git a/kogito-bom/pom.xml b/kogito-bom/pom.xml index 6e4af07c46d..13acf8c5126 100755 --- a/kogito-bom/pom.xml +++ b/kogito-bom/pom.xml @@ -781,18 +781,6 @@ sources - - org.kie - kie-addons-springboot-flyway - ${project.version} - - - org.kie - kie-addons-springboot-flyway - ${project.version} - sources - - org.kie.kogito @@ -1732,6 +1720,59 @@ sources + + + org.jbpm + jbpm-addons-usertask-storage-jpa + ${project.version} + + + org.jbpm + jbpm-addons-usertask-storage-jpa + ${project.version} + sources + + + org.jbpm + jbpm-addons-usertask-storage-jpa + ${project.version} + test-jar + test + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa + ${project.version} + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa + ${project.version} + sources + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa-deployment + ${project.version} + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa-deployment + ${project.version} + sources + + + org.jbpm + jbpm-addons-springboot-usertask-storage-jpa + ${project.version} + + + org.jbpm + jbpm-addons-springboot-usertask-storage-jpa + ${project.version} + sources + + org.kie @@ -1766,7 +1807,17 @@ ${project.version} sources - + + org.kie + kie-addons-springboot-flyway + ${project.version} + + + org.kie + kie-addons-springboot-flyway + ${project.version} + sources + diff --git a/kogito-build/kogito-dependencies-bom/pom.xml b/kogito-build/kogito-dependencies-bom/pom.xml index 26fae00aa0d..f085d103e0a 100644 --- a/kogito-build/kogito-dependencies-bom/pom.xml +++ b/kogito-build/kogito-dependencies-bom/pom.xml @@ -108,6 +108,8 @@ 7.10.2 3.1.0 + 3.1.0 + 6.2.7.Final 24.0.4 @@ -443,6 +445,12 @@ ${version.jakarta.ws.rs} + + jakarta.persistence + jakarta.persistence-api + ${version.jakarta.persistence-api} + + org.junit.jupiter junit-jupiter-api diff --git a/quarkus/addons/flyway/deployment/pom.xml b/quarkus/addons/flyway/deployment/pom.xml index 1e6eefccdc8..de160bad027 100644 --- a/quarkus/addons/flyway/deployment/pom.xml +++ b/quarkus/addons/flyway/deployment/pom.xml @@ -50,6 +50,7 @@ io.quarkus quarkus-agroal-deployment + org.mockito diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/deployment/pom.xml b/quarkus/addons/jbpm-usertask-storage-jpa/deployment/pom.xml new file mode 100644 index 00000000000..fe131a6e27f --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/deployment/pom.xml @@ -0,0 +1,110 @@ + + + + + jbpm-addon-quarkus-usertask-storage-jpa-parent + org.jbpm + 999-SNAPSHOT + + 4.0.0 + + jbpm-addons-quarkus-usertask-storage-jpa-deployment + jBPM :: Add-Ons :: Quarkus :: User Task Storage JPA :: Deployment + jBPM Add-On Quarkus User Task Storage JPA Deployment + + + UTF-8 + org.jbpm.usertask.storage.jpa.quarkus.deployment + + + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa + + + org.kie + kogito-addons-quarkus-common-deployment + + + org.kie + kie-addons-quarkus-flyway-deployment + + + + io.quarkus + quarkus-arc-deployment + + + io.quarkus + quarkus-agroal-deployment + + + io.quarkus + quarkus-hibernate-orm-deployment + + + + io.quarkus + quarkus-junit5 + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + test + + + io.rest-assured + rest-assured + test + + + io.quarkus + quarkus-junit5-mockito + test + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${version.io.quarkus} + + + + + + + \ No newline at end of file diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/deployment/src/main/java/org/jbpm/usertask/storage/jpa/quarkus/deployment/JBPMUserTaskStorageJPAExtensionProcessor.java b/quarkus/addons/jbpm-usertask-storage-jpa/deployment/src/main/java/org/jbpm/usertask/storage/jpa/quarkus/deployment/JBPMUserTaskStorageJPAExtensionProcessor.java new file mode 100644 index 00000000000..6d7087a4716 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/deployment/src/main/java/org/jbpm/usertask/storage/jpa/quarkus/deployment/JBPMUserTaskStorageJPAExtensionProcessor.java @@ -0,0 +1,40 @@ +/* + * 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.usertask.storage.jpa.quarkus.deployment; + +import org.kie.kogito.quarkus.addons.common.deployment.KogitoCapability; +import org.kie.kogito.quarkus.addons.common.deployment.RequireCapabilityKogitoAddOnProcessor; + +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; + +public class JBPMUserTaskStorageJPAExtensionProcessor extends RequireCapabilityKogitoAddOnProcessor { + + private static final String FEATURE = "jbpm-addon-usertask-storage-jpa"; + + public JBPMUserTaskStorageJPAExtensionProcessor() { + super(KogitoCapability.PROCESSES); + } + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/pom.xml b/quarkus/addons/jbpm-usertask-storage-jpa/pom.xml new file mode 100644 index 00000000000..1fc1709a355 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/pom.xml @@ -0,0 +1,45 @@ + + + + + kogito-addons-quarkus-parent + org.kie + 999-SNAPSHOT + + 4.0.0 + + org.jbpm + jbpm-addon-quarkus-usertask-storage-jpa-parent + + jBPM :: Add-Ons :: Quarkus :: User Task Storage JPA :: Parent + jBPM Add-On Quarkus User Task Storage JPA Parent + + pom + + + deployment + runtime + + + \ No newline at end of file diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/pom.xml b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/pom.xml new file mode 100644 index 00000000000..e7808950852 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/pom.xml @@ -0,0 +1,170 @@ + + + + + jbpm-addon-quarkus-usertask-storage-jpa-parent + org.jbpm + 999-SNAPSHOT + + 4.0.0 + + jbpm-addons-quarkus-usertask-storage-jpa + jBPM :: Add-Ons :: Quarkus :: User Task Storage JPA :: Runtime + jBPM Add-On Quarkus User Task Storage JPA Runtime + + + UTF-8 + org.jbpm.usertask.storage.jpa.quarkus + + + + + org.jbpm + jbpm-addons-usertask-storage-jpa + + + org.kie + kie-addons-quarkus-flyway + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-hibernate-orm + + + + io.quarkus + quarkus-agroal + test + + + io.quarkus + quarkus-jdbc-postgresql + test + + + io.quarkus + quarkus-jdbc-h2 + test + + + io.quarkus + quarkus-test-h2 + test + + + io.quarkus + quarkus-junit5 + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + test + + + io.quarkus + quarkus-junit5-mockito + test + + + org.kie.kogito + kogito-quarkus-test-utils + test + + + org.jbpm + jbpm-addons-usertask-storage-jpa + test-jar + test + + + + + + io.quarkus + quarkus-extension-maven-plugin + ${version.io.quarkus} + + + compile + + extension-descriptor + + + ${project.groupId}:${project.artifactId}-deployment:${project.version} + + org.jbpm.addons.usertask.storage + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${version.io.quarkus} + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + org.jboss.logmanager.LogManager + + + + + default + + integration-test + + + + verify + + verify + + + + + + + + \ No newline at end of file diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/QuarkusJPAUserTaskInstances.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/QuarkusJPAUserTaskInstances.java new file mode 100644 index 00000000000..d1cdbef5eb4 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/QuarkusJPAUserTaskInstances.java @@ -0,0 +1,42 @@ +/* + * 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.usertask.jpa.quarkus; + +import org.jbpm.usertask.jpa.JPAUserTaskInstances; +import org.jbpm.usertask.jpa.mapper.UserTaskInstanceEntityMapper; +import org.jbpm.usertask.jpa.repository.UserTaskInstanceRepository; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +@Transactional +@ApplicationScoped +public class QuarkusJPAUserTaskInstances extends JPAUserTaskInstances { + + QuarkusJPAUserTaskInstances() { + super(null, null); + } + + @Inject + public QuarkusJPAUserTaskInstances(UserTaskInstanceRepository userTaskInstanceRepository, UserTaskInstanceEntityMapper userTaskInstanceEntityMapper) { + super(userTaskInstanceRepository, userTaskInstanceEntityMapper); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusAttachmentsEntityMapper.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusAttachmentsEntityMapper.java new file mode 100644 index 00000000000..cb642a4334c --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusAttachmentsEntityMapper.java @@ -0,0 +1,39 @@ +/* + * 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.usertask.jpa.quarkus.mapper; + +import org.jbpm.usertask.jpa.mapper.AttachmentsEntityMapper; +import org.jbpm.usertask.jpa.repository.AttachmentRepository; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusAttachmentsEntityMapper extends AttachmentsEntityMapper { + + QuarkusAttachmentsEntityMapper() { + this(null); + } + + @Inject + public QuarkusAttachmentsEntityMapper(AttachmentRepository attachmentRepository) { + super(attachmentRepository); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusCommentsEntityMapper.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusCommentsEntityMapper.java new file mode 100644 index 00000000000..0024b10a31e --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusCommentsEntityMapper.java @@ -0,0 +1,39 @@ +/* + * 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.usertask.jpa.quarkus.mapper; + +import org.jbpm.usertask.jpa.mapper.CommentsEntityMapper; +import org.jbpm.usertask.jpa.repository.CommentRepository; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusCommentsEntityMapper extends CommentsEntityMapper { + + public QuarkusCommentsEntityMapper() { + this(null); + } + + @Inject + public QuarkusCommentsEntityMapper(CommentRepository commentRepository) { + super(commentRepository); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskInputsEntityMapper.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskInputsEntityMapper.java new file mode 100644 index 00000000000..1304468655e --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskInputsEntityMapper.java @@ -0,0 +1,39 @@ +/* + * 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.usertask.jpa.quarkus.mapper; + +import org.jbpm.usertask.jpa.mapper.TaskInputsEntityMapper; +import org.jbpm.usertask.jpa.repository.TaskInputRepository; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusTaskInputsEntityMapper extends TaskInputsEntityMapper { + + public QuarkusTaskInputsEntityMapper() { + this(null); + } + + @Inject + public QuarkusTaskInputsEntityMapper(TaskInputRepository repository) { + super(repository); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskMetadataEntityMapper.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskMetadataEntityMapper.java new file mode 100644 index 00000000000..fdc5b94360a --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskMetadataEntityMapper.java @@ -0,0 +1,39 @@ +/* + * 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.usertask.jpa.quarkus.mapper; + +import org.jbpm.usertask.jpa.mapper.TaskMetadataEntityMapper; +import org.jbpm.usertask.jpa.repository.TaskMetadataRepository; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusTaskMetadataEntityMapper extends TaskMetadataEntityMapper { + + public QuarkusTaskMetadataEntityMapper() { + this(null); + } + + @Inject + public QuarkusTaskMetadataEntityMapper(TaskMetadataRepository repository) { + super(repository); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskOutputsEntityMapper.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskOutputsEntityMapper.java new file mode 100644 index 00000000000..0d80b25e24b --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusTaskOutputsEntityMapper.java @@ -0,0 +1,39 @@ +/* + * 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.usertask.jpa.quarkus.mapper; + +import org.jbpm.usertask.jpa.mapper.TaskOutputsEntityMapper; +import org.jbpm.usertask.jpa.repository.TaskOutputRepository; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusTaskOutputsEntityMapper extends TaskOutputsEntityMapper { + + public QuarkusTaskOutputsEntityMapper() { + this(null); + } + + @Inject + public QuarkusTaskOutputsEntityMapper(TaskOutputRepository repository) { + super(repository); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusUserTaskInstanceEntityMapper.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusUserTaskInstanceEntityMapper.java new file mode 100644 index 00000000000..e3f6c79e1ad --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/mapper/QuarkusUserTaskInstanceEntityMapper.java @@ -0,0 +1,39 @@ +/* + * 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.usertask.jpa.quarkus.mapper; + +import org.jbpm.usertask.jpa.mapper.*; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusUserTaskInstanceEntityMapper extends UserTaskInstanceEntityMapper { + + QuarkusUserTaskInstanceEntityMapper() { + this(null, null, null, null, null); + } + + @Inject + public QuarkusUserTaskInstanceEntityMapper(AttachmentsEntityMapper attachmentsMapper, CommentsEntityMapper commentsMapper, TaskMetadataEntityMapper taskMetadataEntityMapper, + TaskInputsEntityMapper taskInputsEntityMapper, TaskOutputsEntityMapper taskOutputsEntityMapper) { + super(attachmentsMapper, commentsMapper, taskMetadataEntityMapper, taskInputsEntityMapper, taskOutputsEntityMapper); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusAttachmentRepository.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusAttachmentRepository.java new file mode 100644 index 00000000000..04a551660d5 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusAttachmentRepository.java @@ -0,0 +1,41 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.AttachmentRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +@ApplicationScoped +@Transactional +public class QuarkusAttachmentRepository extends AttachmentRepository { + + QuarkusAttachmentRepository() { + this(null); + } + + @Inject + public QuarkusAttachmentRepository(UserTaskJPAContext context) { + super(context); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusCommentRepository.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusCommentRepository.java new file mode 100644 index 00000000000..7bfecdb4c2e --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusCommentRepository.java @@ -0,0 +1,41 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.CommentRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +@ApplicationScoped +@Transactional +public class QuarkusCommentRepository extends CommentRepository { + + QuarkusCommentRepository() { + this(null); + } + + @Inject + public QuarkusCommentRepository(UserTaskJPAContext context) { + super(context); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskInputEntityRepository.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskInputEntityRepository.java new file mode 100644 index 00000000000..41818d7e0c7 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskInputEntityRepository.java @@ -0,0 +1,40 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.TaskInputRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusTaskInputEntityRepository extends TaskInputRepository { + + QuarkusTaskInputEntityRepository() { + this(null); + } + + @Inject + public QuarkusTaskInputEntityRepository(UserTaskJPAContext context) { + super(context); + } + +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskMetadataEntityRepository.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskMetadataEntityRepository.java new file mode 100644 index 00000000000..6ff95bdf79c --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskMetadataEntityRepository.java @@ -0,0 +1,40 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.TaskMetadataRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusTaskMetadataEntityRepository extends TaskMetadataRepository { + + QuarkusTaskMetadataEntityRepository() { + this(null); + } + + @Inject + public QuarkusTaskMetadataEntityRepository(UserTaskJPAContext context) { + super(context); + } + +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskOutputEntityRepository.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskOutputEntityRepository.java new file mode 100644 index 00000000000..7810b987848 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusTaskOutputEntityRepository.java @@ -0,0 +1,40 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.TaskOutputRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class QuarkusTaskOutputEntityRepository extends TaskOutputRepository { + + QuarkusTaskOutputEntityRepository() { + this(null); + } + + @Inject + public QuarkusTaskOutputEntityRepository(UserTaskJPAContext context) { + super(context); + } + +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusUserTaskInstanceRepository.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusUserTaskInstanceRepository.java new file mode 100644 index 00000000000..2a487fb8bfb --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusUserTaskInstanceRepository.java @@ -0,0 +1,41 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.UserTaskInstanceRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +@ApplicationScoped +@Transactional +public class QuarkusUserTaskInstanceRepository extends UserTaskInstanceRepository { + + QuarkusUserTaskInstanceRepository() { + this(null); + } + + @Inject + public QuarkusUserTaskInstanceRepository(UserTaskJPAContext context) { + super(context); + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusUserTaskJPAContext.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusUserTaskJPAContext.java new file mode 100644 index 00000000000..bcbfb1e366b --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/java/org/jbpm/usertask/jpa/quarkus/repository/QuarkusUserTaskJPAContext.java @@ -0,0 +1,40 @@ +/* + * 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.usertask.jpa.quarkus.repository; + +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.transaction.Transactional; + +@ApplicationScoped +@Transactional +public class QuarkusUserTaskJPAContext implements UserTaskJPAContext { + + @PersistenceContext + private EntityManager em; + + @Override + public EntityManager getEntityManager() { + return em; + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/resources/META-INF/beans.xml b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000000..a0eb9fbf8cd --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/resources/META-INF/beans.xml @@ -0,0 +1,20 @@ + diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 00000000000..4983be32275 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,37 @@ +# +# 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: jBPM User Task Storage JPS +description: Add-On that enables JPA storage for jBPM User Tasks +metadata: + keywords: + - KIE + - jBPM + - persistence + - JPA + guide: https://quarkus.io/guides/kie + categories: + - "business-automation" + - "cloud" + - "jBPM" + - "persistence" + - "JPA" + status: "stable" + config: + - "org.jbpm" diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/BaseQuarkusJPAUserTaskInstancesTest.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/BaseQuarkusJPAUserTaskInstancesTest.java new file mode 100644 index 00000000000..1bfcc273af6 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/BaseQuarkusJPAUserTaskInstancesTest.java @@ -0,0 +1,462 @@ +/* + * 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.usertask.jpa.quarkus; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.function.Function; + +import org.assertj.core.api.Assertions; +import org.jbpm.usertask.jpa.JPAUserTaskInstances; +import org.jbpm.usertask.jpa.mapper.utils.TestUtils; +import org.jbpm.usertask.jpa.model.UserTaskInstanceEntity; +import org.jbpm.usertask.jpa.quarkus.repository.QuarkusUserTaskJPAContext; +import org.jbpm.usertask.jpa.repository.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.kie.kogito.auth.IdentityProviders; +import org.kie.kogito.usertask.UserTaskInstance; +import org.kie.kogito.usertask.impl.DefaultUserTaskInstance; +import org.kie.kogito.usertask.model.Attachment; +import org.kie.kogito.usertask.model.Comment; +import org.mockito.Mockito; + +import jakarta.inject.Inject; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public abstract class BaseQuarkusJPAUserTaskInstancesTest { + + @Inject + QuarkusUserTaskJPAContext context; + + @Inject + JPAUserTaskInstances userTaskInstances; + + @Inject + UserTaskInstanceRepository userTaskInstanceRepository; + + @Inject + AttachmentRepository attachmentRepository; + + @Inject + CommentRepository commentRepository; + + private Function connect; + private Function disconnect; + + @BeforeEach + public void init() { + connect = Mockito.mock(Function.class); + disconnect = Mockito.mock(Function.class); + + when(connect.apply(any(UserTaskInstance.class))).thenAnswer(i -> i.getArgument(0)); + when(disconnect.apply(any(UserTaskInstance.class))).thenAnswer(i -> i.getArgument(0)); + + userTaskInstances.setReconnectUserTaskInstance(connect); + userTaskInstances.setDisconnectUserTaskInstance(disconnect); + } + + @Test + public void testCreateUserTask() { + UserTaskInstance instance = createUserTaskInstance(); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + + Assertions.assertThat(userTaskInstances.findById(instance.getId())) + .isNotNull() + .isEmpty(); + + userTaskInstances.create(instance); + + verify(connect, times(1)).apply(any(UserTaskInstance.class)); + + Optional entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + Assertions.assertThat(entityOptional) + .isNotNull() + .isPresent(); + + UserTaskInstanceEntity entity = entityOptional.get(); + + assertEntityAndInstance(entity, instance); + + Optional persistedInstanceOptional = userTaskInstances.findById(instance.getId()); + + Assertions.assertThat(persistedInstanceOptional) + .isNotNull() + .isPresent(); + + assertEntityAndInstance(entity, persistedInstanceOptional.get()); + } + + @Test + public void testCreateExistingTask() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + Assertions.assertThatThrownBy(() -> userTaskInstances.create(instance)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Task Already exists."); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testEditTaskInputOutputs() { + + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + Optional entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + Assertions.assertThat(entityOptional) + .isNotNull() + .isPresent(); + + UserTaskInstanceEntity entity = entityOptional.get(); + + Assertions.assertThat(entity.getInputs()) + .hasSize(instance.getInputs().size()); + + Assertions.assertThat(entity.getOutputs()) + .hasSize(instance.getOutputs().size()); + + instance.getInputs().clear(); + instance.setInput("new_input", "this is a new input"); + + instance.getOutputs().clear(); + instance.setOutput("new_output", "this is a new output"); + + userTaskInstances.update(instance); + + entity = userTaskInstanceRepository.findById(instance.getId()).get(); + + Assertions.assertThat(entity.getInputs()) + .hasSize(1); + + Assertions.assertThat(entity.getOutputs()) + .hasSize(1); + + TestUtils.assertUserTaskEntityInputs(entity, instance); + TestUtils.assertUserTaskEntityOutputs(entity, instance); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + + } + + @Test + public void testFindByIdentityByActualOwner() { + + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Homer", "Group")); + + Assertions.assertThat(result) + .hasSize(1); + + verify(connect, times(2)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testFindByIdentityByPotentialOwners() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Liza", "Group")); + + Assertions.assertThat(result) + .hasSize(1); + + verify(connect, times(2)).apply(any(UserTaskInstance.class)); + + List result2 = userTaskInstances.findByIdentity(IdentityProviders.of("Bart", "Simpson")); + + Assertions.assertThat(result2) + .hasSize(1); + + verify(connect, times(3)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testFindByIdentityByPotentialGroups() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Abraham", "Admin", "Simpson")); + + Assertions.assertThat(result) + .hasSize(1); + + verify(connect, times(2)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testFindByIdentityByAdminUsers() { + + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Seymour", "Group")); + + Assertions.assertThat(result) + .hasSize(1); + + verify(connect, times(2)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testFindByIdentityByAdminGroups() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Abraham", "Administrator", "Managers")); + + Assertions.assertThat(result) + .hasSize(1); + + verify(connect, times(2)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testFindByIdentityByExcludedUser() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Ned")); + + Assertions.assertThat(result) + .hasSize(0); + + verify(connect, times(1)).apply(any(UserTaskInstance.class)); + + result = userTaskInstances.findByIdentity(IdentityProviders.of("Bart")); + + Assertions.assertThat(result) + .hasSize(0); + + verify(connect, times(1)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testFindByIdentityByUnknownUser() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + List result = userTaskInstances.findByIdentity(IdentityProviders.of("Someone", "Group")); + + Assertions.assertThat(result) + .hasSize(0); + + verify(connect, times(1)).apply(any(UserTaskInstance.class)); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testAttachments() throws URISyntaxException { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + Optional entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + Assertions.assertThat(entityOptional) + .isNotNull() + .isPresent(); + + assertEntityAndInstance(entityOptional.get(), instance); + + Attachment attachment = new Attachment("1", "Admin"); + attachment.setName("attachment 1"); + attachment.setContent(new URI("http://url.com/to/my/attachment")); + attachment.setUpdatedAt(new Date()); + + instance.addAttachment(attachment); + + entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + TestUtils.assertUserTaskEntityAttachments(entityOptional.get().getAttachments(), instance.getAttachments()); + + Attachment attachment2 = new Attachment("2", "Admin"); + attachment2.setName("attachment 2"); + attachment2.setContent(new URI("http://url.com/to/my/attachment2")); + attachment2.setUpdatedAt(new Date()); + + instance.addAttachment(attachment2); + + entityOptional = userTaskInstanceRepository.findById(instance.getId()); + TestUtils.assertUserTaskEntityAttachments(entityOptional.get().getAttachments(), instance.getAttachments()); + + instance.removeAttachment(attachment); + instance.removeAttachment(attachment2); + + userTaskInstances.update(instance); + + entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + Assertions.assertThat(entityOptional.get().getAttachments()) + .isEmpty(); + + Assertions.assertThat(attachmentRepository.findAll()) + .isEmpty(); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + @Test + public void testComments() { + UserTaskInstance instance = createUserTaskInstance(); + + userTaskInstances.create(instance); + + Optional entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + Assertions.assertThat(entityOptional) + .isNotNull() + .isPresent(); + + assertEntityAndInstance(entityOptional.get(), instance); + + Comment comment = new Comment("1", "Admin"); + comment.setContent("This the comment 1"); + comment.setUpdatedAt(new Date()); + + instance.addComment(comment); + + entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + UserTaskInstanceEntity userTaskInstanceEntity = entityOptional.get(); + + Assertions.assertThat(userTaskInstanceEntity.getComments()) + .hasSize(1); + + TestUtils.assertUserTaskEntityComments(entityOptional.get().getComments(), instance.getComments()); + + Comment comment2 = new Comment("2", "Admin"); + comment2.setContent("This the comment 2"); + comment2.setUpdatedAt(new Date()); + + instance.addComment(comment2); + + entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + userTaskInstanceEntity = entityOptional.get(); + + Assertions.assertThat(userTaskInstanceEntity.getComments()) + .hasSize(2); + + TestUtils.assertUserTaskEntityComments(userTaskInstanceEntity.getComments(), instance.getComments()); + + instance.removeComment(comment); + instance.removeComment(comment2); + + entityOptional = userTaskInstanceRepository.findById(instance.getId()); + + Assertions.assertThat(entityOptional.get().getComments()) + .isEmpty(); + + Assertions.assertThat(commentRepository.findAll()) + .isEmpty(); + + userTaskInstances.remove(instance); + + Assertions.assertThat(userTaskInstances.exists(instance.getId())) + .isFalse(); + } + + private void assertEntityAndInstance(UserTaskInstanceEntity entity, UserTaskInstance instance) { + TestUtils.assertUserTaskEntityData(entity, instance); + + TestUtils.assertUserTaskEntityPotentialUserAndGroups(entity, instance); + TestUtils.assertUserTaskEntityAdminUserAndGroups(entity, instance); + TestUtils.assertUserTaskEntityExcludedUsers(entity, instance); + + TestUtils.assertUserTaskEntityInputs(entity, instance); + TestUtils.assertUserTaskEntityOutputs(entity, instance); + + TestUtils.assertUserTaskEntityAttachments(entity.getAttachments(), instance.getAttachments()); + TestUtils.assertUserTaskEntityComments(entity.getComments(), instance.getComments()); + TestUtils.assertUserTaskEntityMetadata(entity, instance); + } + + private UserTaskInstance createUserTaskInstance() { + DefaultUserTaskInstance instance = TestUtils.createUserTaskInstance(); + + instance.setInstances(userTaskInstances); + + return instance; + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/H2QuarkusJPAUserTaskInstancesTest.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/H2QuarkusJPAUserTaskInstancesTest.java new file mode 100644 index 00000000000..f314b629be5 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/H2QuarkusJPAUserTaskInstancesTest.java @@ -0,0 +1,33 @@ +/* + * 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.usertask.jpa.quarkus; + +import io.quarkus.test.TestTransaction; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.h2.H2DatabaseTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestTransaction +@QuarkusTestResource(value = H2DatabaseTestResource.class, restrictToAnnotatedClass = true) +@TestProfile(H2QuarkusTestProfile.class) +public class H2QuarkusJPAUserTaskInstancesTest extends BaseQuarkusJPAUserTaskInstancesTest { +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/H2QuarkusTestProfile.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/H2QuarkusTestProfile.java new file mode 100644 index 00000000000..4a1b05ffec8 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/H2QuarkusTestProfile.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.jbpm.usertask.jpa.quarkus; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class H2QuarkusTestProfile implements QuarkusTestProfile { + + @Override + public String getConfigProfile() { + return "test-h2"; + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/PostgreSQLQuarkusJPAUserTaskInstancesTest.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/PostgreSQLQuarkusJPAUserTaskInstancesTest.java new file mode 100644 index 00000000000..7174ee048c3 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/PostgreSQLQuarkusJPAUserTaskInstancesTest.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.quarkus; + +import org.kie.kogito.testcontainers.quarkus.PostgreSqlQuarkusTestResource; + +import io.quarkus.test.TestTransaction; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; + +@QuarkusTest +@TestTransaction +@QuarkusTestResource(value = PostgreSqlQuarkusTestResource.class, restrictToAnnotatedClass = true) +@TestProfile(PostgreSQLQuarkusTestProfile.class) +public class PostgreSQLQuarkusJPAUserTaskInstancesTest extends BaseQuarkusJPAUserTaskInstancesTest { + +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/PostgreSQLQuarkusTestProfile.java b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/PostgreSQLQuarkusTestProfile.java new file mode 100644 index 00000000000..dda90d34319 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/java/org/jbpm/usertask/jpa/quarkus/PostgreSQLQuarkusTestProfile.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.jbpm.usertask.jpa.quarkus; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class PostgreSQLQuarkusTestProfile implements QuarkusTestProfile { + + @Override + public String getConfigProfile() { + return "test-postgresql"; + } +} diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/resources/META-INF/beans.xml b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/resources/META-INF/beans.xml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/resources/application.properties b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/resources/application.properties new file mode 100644 index 00000000000..62677c92319 --- /dev/null +++ b/quarkus/addons/jbpm-usertask-storage-jpa/runtime/src/test/resources/application.properties @@ -0,0 +1,28 @@ +# +# 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. +# + + +%test-postgresql.quarkus.datasource.db-kind=postgresql +%test-postgresql.quarkus.datasource.devservices.enabled=false + +%test-h2.quarkus.datasource.db-kind=h2 +%test-h2.quarkus.datasource.username=kogito +%test-h2.quarkus.datasource.jdbc.url=jdbc:h2:mem:default + +kie.flyway.enabled=true diff --git a/quarkus/addons/pom.xml b/quarkus/addons/pom.xml index 2a51d08ca82..de5f6685ed0 100644 --- a/quarkus/addons/pom.xml +++ b/quarkus/addons/pom.xml @@ -60,6 +60,7 @@ marshallers process-definitions dynamic + jbpm-usertask-storage-jpa diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/pom.xml b/quarkus/integration-tests/integration-tests-quarkus-usertasks/pom.xml new file mode 100644 index 00000000000..e648118be0c --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/pom.xml @@ -0,0 +1,146 @@ + + + + + org.kie.kogito + kogito-quarkus-integration-tests + 999-SNAPSHOT + + 4.0.0 + integration-tests-quarkus-usertasks + Kogito :: Integration Tests :: Quarkus :: Processes :: Source Files + + + org.jbpm.usertask.storage.jpa.quarkus.it + + + + + + org.kie.kogito + kogito-quarkus-bom + ${project.version} + pom + import + + + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-resteasy-jackson + + + org.jbpm + jbpm-quarkus + + + org.kie + kie-addons-quarkus-persistence-jdbc + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-agroal + + + io.quarkus + quarkus-jdbc-postgresql + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.assertj + assertj-core + test + + + org.kie.kogito + kogito-quarkus-test-utils + test + + + + + org.jbpm + jbpm-quarkus-deployment + ${project.version} + pom + test + + + * + * + + + + + org.jbpm + jbpm-addons-quarkus-usertask-storage-jpa-deployment + ${project.version} + pom + test + + + * + * + + + + + + + + + io.quarkus + quarkus-maven-plugin + + + + build + + + + + + + \ No newline at end of file diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/java/org/acme/travels/Address.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/java/org/acme/travels/Address.java new file mode 100644 index 00000000000..662dfa9b9f7 --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/java/org/acme/travels/Address.java @@ -0,0 +1,76 @@ +/* + * 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.acme.travels; + +public class Address { + + private String street; + private String city; + private String zipCode; + private String country; + + public Address() { + + } + + public Address(String street, String city, String zipCode, String country) { + super(); + this.street = street; + this.city = city; + this.zipCode = zipCode; + this.country = country; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public String toString() { + return "Address [street=" + street + ", city=" + city + ", zipCode=" + zipCode + ", country=" + country + "]"; + } +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/java/org/acme/travels/Traveller.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/java/org/acme/travels/Traveller.java new file mode 100644 index 00000000000..c24685803d2 --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/java/org/acme/travels/Traveller.java @@ -0,0 +1,88 @@ +/* + * 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.acme.travels; + +public class Traveller { + + private String firstName; + private String lastName; + private String email; + private String nationality; + private Address address; + + public Traveller() { + + } + + public Traveller(String firstName, String lastName, String email, String nationality, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.nationality = nationality; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getNationality() { + return nationality; + } + + public void setNationality(String nationality) { + this.nationality = nationality; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + @Override + public String toString() { + return "Traveller [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", nationality=" + + nationality + ", address=" + address + "]"; + } + +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/resources/application.properties b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/resources/application.properties new file mode 100644 index 00000000000..5458fa57f9c --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/resources/application.properties @@ -0,0 +1,24 @@ +# +# 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. +# + +quarkus.datasource.db-kind=postgresql + +kogito.persistence.type=jdbc + +kie.flyway.enabled=true \ No newline at end of file diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/resources/approval.bpmn b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/resources/approval.bpmn new file mode 100644 index 00000000000..275d148f7ac --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/main/resources/approval.bpmn @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _9EAFE6C1-69B4-4908-B764-EF3C4A55BEE3 + _C13522F1-230A-4C26-B5A9-533A5D9FEE9D + + + + + + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_travellerInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_ActorIdOutputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_approvedOutputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + + + + traveller + _8B62D3CA-5D03-4B2B-832B-126469288BB4_travellerInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_ActorIdOutputX + approver + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_approvedOutputX + firstLineApproval + + + + manager + + + + + + + + + + _C13522F1-230A-4C26-B5A9-533A5D9FEE9D + _078F46FB-B7A1-4DBB-BE9A-75C7CB0CCD03 + + + + + + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_ExcludedOwnerIdInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_travellerInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_approvedOutputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + + + + approver + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_ExcludedOwnerIdInputX + + + traveller + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_travellerInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_approvedOutputX + secondLineApproval + + + + + + + + + _9EAFE6C1-69B4-4908-B764-EF3C4A55BEE3 + + + + + + + + _078F46FB-B7A1-4DBB-BE9A-75C7CB0CCD03 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _F0jB8En5EeqlfsIhq1UCRQ + _F0jB8En5EeqlfsIhq1UCRQ + + diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/BaseUserTaskIT.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/BaseUserTaskIT.java new file mode 100644 index 00000000000..1d75f4c0c5a --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/BaseUserTaskIT.java @@ -0,0 +1,69 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Traveller; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.emptyOrNullString; + +public abstract class BaseUserTaskIT { + public static final String PROCESS_ID = "approvals"; + public static final String USER_TASKS_ENDPOINT = "/usertasks/instance"; + public static final String USER_TASKS_INSTANCE_ENDPOINT = USER_TASKS_ENDPOINT + "/{taskId}"; + + static { + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + } + + public String startProcessInstance(Traveller traveller) { + final String pid = given().contentType(ContentType.JSON) + .when() + .body(Map.of("traveller", traveller)) + .post("/{processId}", PROCESS_ID) + .then() + .statusCode(201) + .header("Location", not(emptyOrNullString())) + .body("id", not(emptyOrNullString())) + .extract() + .path("id"); + + given() + .accept(ContentType.JSON) + .when() + .get("/{processId}/{id}", PROCESS_ID, pid) + .then() + .statusCode(200) + .body("id", equalTo(pid)) + .body("traveller.firstName", equalTo(traveller.getFirstName())) + .body("traveller.lastName", equalTo(traveller.getLastName())) + .body("traveller.email", equalTo(traveller.getEmail())) + .body("traveller.nationality", equalTo(traveller.getNationality())); + + return pid; + } +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskAttachmentsIT.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskAttachmentsIT.java new file mode 100644 index 00000000000..630e207040b --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskAttachmentsIT.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.jbpm.userTask.jpa.it; + +import java.net.URI; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.testcontainers.quarkus.PostgreSqlQuarkusTestResource; +import org.kie.kogito.usertask.model.AttachmentInfo; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.emptyOrNullString; + +@QuarkusIntegrationTest +@QuarkusTestResource(value = PostgreSqlQuarkusTestResource.class, restrictToAnnotatedClass = true) +public class UserTaskAttachmentsIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/attachments"; + public static final String USER_TASKS_INSTANCE_ATTACHMENT = USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT + "/{attachmentId}"; + + @Test + public void testUserTaskAttachments() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + AttachmentInfo attachment1 = new AttachmentInfo(URI.create("http://localhost:8080/attachment_1.txt"), "Attachment 1"); + + String attachment1Id = addAndVerifyAttachment(taskId, attachment1); + + AttachmentInfo attachment2 = new AttachmentInfo(URI.create("http://localhost:8080/attachment_2.txt"), "Attachment 2"); + + String attachment2Id = addAndVerifyAttachment(taskId, attachment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)); + + attachment1 = new AttachmentInfo(URI.create("http://localhost:8080/new_attachment_1.txt"), "NEW Attachment 1"); + + updateAndVerifyAttachment(taskId, attachment1Id, attachment1); + + attachment2 = new AttachmentInfo(URI.create("http://localhost:8080/new_attachment_2.txt"), "NEW Attachment 2"); + + updateAndVerifyAttachment(taskId, attachment2Id, attachment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)) + .body("[0].id", not(emptyOrNullString())) + .body("[0].content", equalTo(attachment1.getUri().toString())) + .body("[0].name", equalTo(attachment1.getName())) + .body("[0].updatedBy", not(emptyOrNullString())) + .body("[0].updatedAt", not(emptyOrNullString())) + .body("[1].id", not(emptyOrNullString())) + .body("[1].content", equalTo(attachment2.getUri().toString())) + .body("[1].name", equalTo(attachment2.getName())) + .body("[1].updatedBy", not(emptyOrNullString())) + .body("[1].updatedAt", not(emptyOrNullString())); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachment1Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(1)); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachment2Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + } + + private String addAndVerifyAttachment(String taskId, AttachmentInfo attachment) { + String id = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(attachment) + .post(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENT, taskId, id) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + + return id; + } + + private void updateAndVerifyAttachment(String taskId, String attachmentId, AttachmentInfo attachment) { + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(attachment) + .put(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachmentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachmentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + } +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskCommentsIT.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskCommentsIT.java new file mode 100644 index 00000000000..638c7e30266 --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskCommentsIT.java @@ -0,0 +1,203 @@ +/* + * 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.userTask.jpa.it; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.testcontainers.quarkus.PostgreSqlQuarkusTestResource; +import org.kie.kogito.usertask.model.CommentInfo; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.emptyOrNullString; + +@QuarkusIntegrationTest +@QuarkusTestResource(value = PostgreSqlQuarkusTestResource.class, restrictToAnnotatedClass = true) +public class UserTaskCommentsIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_COMMENTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/comments"; + public static final String USER_TASKS_INSTANCE_COMMENT = USER_TASKS_INSTANCE_COMMENTS_ENDPOINT + "/{commentId}"; + + @Test + public void testUserTaskComments() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + CommentInfo comment1 = new CommentInfo("This is my second comment."); + + String comment1Id = addAndVerifyComment(taskId, comment1); + + CommentInfo comment2 = new CommentInfo("This is my second comment."); + + String comment2Id = addAndVerifyComment(taskId, comment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)); + + comment1 = new CommentInfo("This is the first comment modified"); + + updateAndVerifyComment(taskId, comment1Id, comment1); + + comment2 = new CommentInfo("This is the second comment modified"); + + updateAndVerifyComment(taskId, comment2Id, comment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)) + .body("[0].id", not(emptyOrNullString())) + .body("[0].content", equalTo(comment1.getComment())) + .body("[0].updatedBy", not(emptyOrNullString())) + .body("[0].updatedAt", not(emptyOrNullString())) + .body("[1].id", not(emptyOrNullString())) + .body("[1].content", equalTo(comment2.getComment())) + .body("[1].updatedBy", not(emptyOrNullString())) + .body("[1].updatedAt", not(emptyOrNullString())); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_COMMENT, taskId, comment1Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(1)); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_COMMENT, taskId, comment2Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + } + + private String addAndVerifyComment(String taskId, CommentInfo comment) { + String id = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(comment) + .post(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENT, taskId, id) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + + return id; + } + + private void updateAndVerifyComment(String taskId, String commentId, CommentInfo comment) { + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(comment) + .put(USER_TASKS_INSTANCE_COMMENT, taskId, commentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENT, taskId, commentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + } +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskInputs.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskInputs.java new file mode 100644 index 00000000000..13084ed8399 --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskInputs.java @@ -0,0 +1,107 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.testcontainers.quarkus.PostgreSqlQuarkusTestResource; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; + +@QuarkusIntegrationTest +@QuarkusTestResource(value = PostgreSqlQuarkusTestResource.class, restrictToAnnotatedClass = true) +public class UserTaskInputs extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_INPUTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/inputs"; + + @Test + public void testUserTaskInputs() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")) + .body("taskName", equalTo("firstLineApproval")) + .body("potentialUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + Traveller newTraveller = new Traveller("Ned", "Stark", "n.stark@winterfell.com", "Northern", new Address("main street", "Winterfell", "10005", "WF")); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(Map.of("traveller", newTraveller)) + .put(USER_TASKS_INSTANCE_INPUTS_ENDPOINT, taskId) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("inputs.traveller.firstName", equalTo(newTraveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(newTraveller.getLastName())) + .body("inputs.traveller.email", equalTo(newTraveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(newTraveller.getNationality())) + .body("inputs.traveller.address.street", equalTo(newTraveller.getAddress().getStreet())) + .body("inputs.traveller.address.city", equalTo(newTraveller.getAddress().getCity())) + .body("inputs.traveller.address.zipCode", equalTo(newTraveller.getAddress().getZipCode())) + .body("inputs.traveller.address.country", equalTo(newTraveller.getAddress().getCountry())); + } +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskLifeCycleIT.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskLifeCycleIT.java new file mode 100644 index 00000000000..b2c7b29e11d --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskLifeCycleIT.java @@ -0,0 +1,192 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.testcontainers.quarkus.PostgreSqlQuarkusTestResource; +import org.kie.kogito.usertask.model.TransitionInfo; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; + +@QuarkusIntegrationTest +@QuarkusTestResource(value = PostgreSqlQuarkusTestResource.class, restrictToAnnotatedClass = true) +public class UserTaskLifeCycleIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_TRANSITION_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/transition"; + + @Test + public void testUserTaskLifeCycle() { + + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + final String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")) + .body("taskName", equalTo("firstLineApproval")) + .body("potentialUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + given() + .contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(new TransitionInfo("complete", Map.of("approved", true))) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Completed")) + .body("status.terminate", equalTo("COMPLETED")) + .body("outputs.approved", equalTo(true)); + + // Manager is excluded for the secondLineApproval Task, he shouldn't be allowed to see the task + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .body("[0].id", not(taskId)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Ready")) + .body("taskName", equalTo("secondLineApproval")) + .body("excludedUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + // Manager is excluded for the secondLineApproval Task, he shouldn't be able to work on the task + given() + .contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .body(new TransitionInfo("claim")) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(500); + + given() + .contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .body(new TransitionInfo("claim")) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")); + + given() + .contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .body(new TransitionInfo("complete", Map.of("approved", true))) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Completed")) + .body("status.terminate", equalTo("COMPLETED")) + .body("outputs.approved", equalTo(true)); + + given() + .accept(ContentType.JSON) + .when() + .get("/{processId}/{id}", PROCESS_ID, pid) + .then() + .statusCode(404); + } +} diff --git a/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskOutputsIT.java b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskOutputsIT.java new file mode 100644 index 00000000000..1192545ac61 --- /dev/null +++ b/quarkus/integration-tests/integration-tests-quarkus-usertasks/src/test/java/org/jbpm/userTask/jpa/it/UserTaskOutputsIT.java @@ -0,0 +1,109 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.testcontainers.quarkus.PostgreSqlQuarkusTestResource; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; + +@QuarkusIntegrationTest +@QuarkusTestResource(value = PostgreSqlQuarkusTestResource.class, restrictToAnnotatedClass = true) +public class UserTaskOutputsIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_OUTPUTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/outputs"; + + @Test + public void testUserTaskOutputs() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")) + .body("taskName", equalTo("firstLineApproval")) + .body("potentialUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + Traveller newTraveller = new Traveller("Ned", "Stark", "n.stark@winterfell.com", "Northern", new Address("main street", "Winterfell", "10005", "WF")); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(Map.of("traveller", newTraveller, "approved", true)) + .put(USER_TASKS_INSTANCE_OUTPUTS_ENDPOINT, taskId) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("outputs.approved", is(true)) + .body("outputs.traveller.firstName", equalTo(newTraveller.getFirstName())) + .body("outputs.traveller.lastName", equalTo(newTraveller.getLastName())) + .body("outputs.traveller.email", equalTo(newTraveller.getEmail())) + .body("outputs.traveller.nationality", equalTo(newTraveller.getNationality())) + .body("outputs.traveller.address.street", equalTo(newTraveller.getAddress().getStreet())) + .body("outputs.traveller.address.city", equalTo(newTraveller.getAddress().getCity())) + .body("outputs.traveller.address.zipCode", equalTo(newTraveller.getAddress().getZipCode())) + .body("outputs.traveller.address.country", equalTo(newTraveller.getAddress().getCountry())); + } +} diff --git a/quarkus/integration-tests/pom.xml b/quarkus/integration-tests/pom.xml index 1fb26d5ec8d..48ba322a8bd 100644 --- a/quarkus/integration-tests/pom.xml +++ b/quarkus/integration-tests/pom.xml @@ -48,6 +48,7 @@ integration-tests-quarkus-processes integration-tests-quarkus-processes-reactive integration-tests-quarkus-processes-persistence + integration-tests-quarkus-usertasks integration-tests-quarkus-source-files integration-tests-quarkus-gradle diff --git a/springboot/addons/jbpm-usertask-storage-jpa/pom.xml b/springboot/addons/jbpm-usertask-storage-jpa/pom.xml new file mode 100644 index 00000000000..36bed41e5cc --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/pom.xml @@ -0,0 +1,35 @@ + + + + kogito-addons-springboot-parent + org.kie + 999-SNAPSHOT + + 4.0.0 + + org.jbpm + jbpm-addons-springboot-usertask-storage-jpa + jBPM :: Add-Ons :: Spring Boot :: User Task Storage JPA + jBPM Add-On Spring Boot User Task Storage JPA + + + UTF-8 + org.jbpm.usertask.storage.jpa.springboot + + + + + org.springframework.boot + spring-boot-starter-web + + + org.jbpm + jbpm-addons-usertask-storage-jpa + + + org.kie + kie-addons-springboot-flyway + + + diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/SpringBootJPAUserTaskInstances.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/SpringBootJPAUserTaskInstances.java new file mode 100644 index 00000000000..aadef95e407 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/SpringBootJPAUserTaskInstances.java @@ -0,0 +1,37 @@ +/* + * 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.usertask.jpa.springboot; + +import org.jbpm.usertask.jpa.JPAUserTaskInstances; +import org.jbpm.usertask.jpa.mapper.UserTaskInstanceEntityMapper; +import org.jbpm.usertask.jpa.repository.UserTaskInstanceRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@Component +public class SpringBootJPAUserTaskInstances extends JPAUserTaskInstances { + + @Autowired + public SpringBootJPAUserTaskInstances(UserTaskInstanceRepository userTaskInstanceRepository, UserTaskInstanceEntityMapper userTaskInstanceEntityMapper) { + super(userTaskInstanceRepository, userTaskInstanceEntityMapper); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootAttachmentsEntityMapper.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootAttachmentsEntityMapper.java new file mode 100644 index 00000000000..6375f27ec8e --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootAttachmentsEntityMapper.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.springboot.mapper; + +import org.jbpm.usertask.jpa.mapper.AttachmentsEntityMapper; +import org.jbpm.usertask.jpa.repository.AttachmentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootAttachmentsEntityMapper extends AttachmentsEntityMapper { + + @Autowired + public SpringBootAttachmentsEntityMapper(AttachmentRepository attachmentRepository) { + super(attachmentRepository); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootCommentsEntityMapper.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootCommentsEntityMapper.java new file mode 100644 index 00000000000..2a8c4cb8215 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootCommentsEntityMapper.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.springboot.mapper; + +import org.jbpm.usertask.jpa.mapper.CommentsEntityMapper; +import org.jbpm.usertask.jpa.repository.CommentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootCommentsEntityMapper extends CommentsEntityMapper { + + @Autowired + public SpringBootCommentsEntityMapper(CommentRepository commentRepository) { + super(commentRepository); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskInputsEntityMapper.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskInputsEntityMapper.java new file mode 100644 index 00000000000..c0520b805b3 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskInputsEntityMapper.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.springboot.mapper; + +import org.jbpm.usertask.jpa.mapper.TaskInputsEntityMapper; +import org.jbpm.usertask.jpa.repository.TaskInputRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootTaskInputsEntityMapper extends TaskInputsEntityMapper { + + @Autowired + public SpringBootTaskInputsEntityMapper(TaskInputRepository repository) { + super(repository); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskMetadataEntityMapper.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskMetadataEntityMapper.java new file mode 100644 index 00000000000..9d52d325084 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskMetadataEntityMapper.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.springboot.mapper; + +import org.jbpm.usertask.jpa.mapper.TaskMetadataEntityMapper; +import org.jbpm.usertask.jpa.repository.TaskMetadataRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootTaskMetadataEntityMapper extends TaskMetadataEntityMapper { + + @Autowired + public SpringBootTaskMetadataEntityMapper(TaskMetadataRepository repository) { + super(repository); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskOutputsEntityMapper.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskOutputsEntityMapper.java new file mode 100644 index 00000000000..83f9634990a --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootTaskOutputsEntityMapper.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.springboot.mapper; + +import org.jbpm.usertask.jpa.mapper.TaskOutputsEntityMapper; +import org.jbpm.usertask.jpa.repository.TaskOutputRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootTaskOutputsEntityMapper extends TaskOutputsEntityMapper { + + @Autowired + public SpringBootTaskOutputsEntityMapper(TaskOutputRepository repository) { + super(repository); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootUserTaskInstanceEntityMapper.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootUserTaskInstanceEntityMapper.java new file mode 100644 index 00000000000..6c753b1b6a0 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/mapper/SpringBootUserTaskInstanceEntityMapper.java @@ -0,0 +1,34 @@ +/* + * 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.usertask.jpa.springboot.mapper; + +import org.jbpm.usertask.jpa.mapper.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootUserTaskInstanceEntityMapper extends UserTaskInstanceEntityMapper { + + @Autowired + public SpringBootUserTaskInstanceEntityMapper(AttachmentsEntityMapper attachmentsMapper, CommentsEntityMapper commentsMapper, TaskMetadataEntityMapper taskMetadataEntityMapper, + TaskInputsEntityMapper taskInputsEntityMapper, TaskOutputsEntityMapper taskOutputsEntityMapper) { + super(attachmentsMapper, commentsMapper, taskMetadataEntityMapper, taskInputsEntityMapper, taskOutputsEntityMapper); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootAttachmentRepository.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootAttachmentRepository.java new file mode 100644 index 00000000000..d9fad245177 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootAttachmentRepository.java @@ -0,0 +1,36 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.AttachmentRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Transactional +public class SpringBootAttachmentRepository extends AttachmentRepository { + + @Autowired + public SpringBootAttachmentRepository(UserTaskJPAContext context) { + super(context); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootCommentRepository.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootCommentRepository.java new file mode 100644 index 00000000000..6181e505e7e --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootCommentRepository.java @@ -0,0 +1,36 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.CommentRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Transactional +public class SpringBootCommentRepository extends CommentRepository { + + @Autowired + public SpringBootCommentRepository(UserTaskJPAContext context) { + super(context); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskInputEntityRepository.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskInputEntityRepository.java new file mode 100644 index 00000000000..468301e813f --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskInputEntityRepository.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.TaskInputRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootTaskInputEntityRepository extends TaskInputRepository { + + @Autowired + public SpringBootTaskInputEntityRepository(UserTaskJPAContext context) { + super(context); + } + +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskMetadataEntityRepository.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskMetadataEntityRepository.java new file mode 100644 index 00000000000..c5064422a82 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskMetadataEntityRepository.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.TaskMetadataRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootTaskMetadataEntityRepository extends TaskMetadataRepository { + + @Autowired + public SpringBootTaskMetadataEntityRepository(UserTaskJPAContext context) { + super(context); + } + +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskOutputEntityRepository.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskOutputEntityRepository.java new file mode 100644 index 00000000000..3eefcd20778 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootTaskOutputEntityRepository.java @@ -0,0 +1,35 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.TaskOutputRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SpringBootTaskOutputEntityRepository extends TaskOutputRepository { + + @Autowired + public SpringBootTaskOutputEntityRepository(UserTaskJPAContext context) { + super(context); + } + +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootUserTaskInstanceRepository.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootUserTaskInstanceRepository.java new file mode 100644 index 00000000000..b84df9dad37 --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootUserTaskInstanceRepository.java @@ -0,0 +1,36 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.UserTaskInstanceRepository; +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Transactional +public class SpringBootUserTaskInstanceRepository extends UserTaskInstanceRepository { + + @Autowired + public SpringBootUserTaskInstanceRepository(UserTaskJPAContext context) { + super(context); + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootUserTaskJPAContext.java b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootUserTaskJPAContext.java new file mode 100644 index 00000000000..a208f7ece9c --- /dev/null +++ b/springboot/addons/jbpm-usertask-storage-jpa/src/main/java/org/jbpm/usertask/jpa/springboot/repository/SpringBootUserTaskJPAContext.java @@ -0,0 +1,40 @@ +/* + * 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.usertask.jpa.springboot.repository; + +import org.jbpm.usertask.jpa.repository.UserTaskJPAContext; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; + +@Component +@Transactional +public class SpringBootUserTaskJPAContext implements UserTaskJPAContext { + + @PersistenceContext + private EntityManager em; + + @Override + public EntityManager getEntityManager() { + return em; + } +} diff --git a/springboot/addons/jbpm-usertask-storage-jpa/src/main/resources/META-INF/beans.xml b/springboot/addons/jbpm-usertask-storage-jpa/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/springboot/addons/pom.xml b/springboot/addons/pom.xml index d6221ca7a6b..3aee177ac61 100644 --- a/springboot/addons/pom.xml +++ b/springboot/addons/pom.xml @@ -51,6 +51,7 @@ kubernetes flyway persistence + jbpm-usertask-storage-jpa diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/pom.xml b/springboot/integration-tests/integration-tests-springboot-usertasks-it/pom.xml new file mode 100644 index 00000000000..d3a7645e5f9 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/pom.xml @@ -0,0 +1,153 @@ + + + + org.kie.kogito + kogito-spring-boot-integration-tests + 999-SNAPSHOT + + + 4.0.0 + + integration-tests-springboot-usertasks-it + Kogito :: Integration Tests :: Spring Boot :: UserTasks + + + integration.tests.springboot.userTasks.it + false + + + + + + org.kie.kogito + kogito-spring-boot-bom + ${project.version} + pom + import + + + + + + + org.jbpm + jbpm-spring-boot-starter + + + org.kie + kie-addons-springboot-persistence-jdbc + + + org.jbpm + jbpm-addons-springboot-usertask-storage-jpa + + + + + org.postgresql + postgresql + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.kie + kie-addons-springboot-process-management + + + org.springframework.boot + spring-boot-starter-test + test + + + io.rest-assured + json-schema-validator + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + io.rest-assured + rest-assured + test + + + org.kie.kogito + kogito-spring-boot-test-utils + test + + + org.awaitility + awaitility + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + maven-compiler-plugin + ${version.compiler.plugin} + + ${maven.compiler.release} + + + + pre-kogito-generate-model + process-resources + + compile + + + + + + org.kie.kogito + kogito-maven-plugin + ${project.version} + + + kogito-generate-model + process-resources + + generateModel + + + + kogito-process-model-classes + process-classes + + process-model-classes + + + + + + + \ No newline at end of file diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/acme/travels/Address.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/acme/travels/Address.java new file mode 100644 index 00000000000..662dfa9b9f7 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/acme/travels/Address.java @@ -0,0 +1,76 @@ +/* + * 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.acme.travels; + +public class Address { + + private String street; + private String city; + private String zipCode; + private String country; + + public Address() { + + } + + public Address(String street, String city, String zipCode, String country) { + super(); + this.street = street; + this.city = city; + this.zipCode = zipCode; + this.country = country; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public String toString() { + return "Address [street=" + street + ", city=" + city + ", zipCode=" + zipCode + ", country=" + country + "]"; + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/acme/travels/Traveller.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/acme/travels/Traveller.java new file mode 100644 index 00000000000..c24685803d2 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/acme/travels/Traveller.java @@ -0,0 +1,88 @@ +/* + * 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.acme.travels; + +public class Traveller { + + private String firstName; + private String lastName; + private String email; + private String nationality; + private Address address; + + public Traveller() { + + } + + public Traveller(String firstName, String lastName, String email, String nationality, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.nationality = nationality; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getNationality() { + return nationality; + } + + public void setNationality(String nationality) { + this.nationality = nationality; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + @Override + public String toString() { + return "Traveller [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", nationality=" + + nationality + ", address=" + address + "]"; + } + +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/kie/kogito/it/KogitoSpringbootApplication.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/kie/kogito/it/KogitoSpringbootApplication.java new file mode 100644 index 00000000000..8cc2437b71d --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/java/org/kie/kogito/it/KogitoSpringbootApplication.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.it; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = { "org.kie.kogito.**", "org.acme.travels.**" }) +public class KogitoSpringbootApplication { + + public static void main(String[] args) { + SpringApplication.run(KogitoSpringbootApplication.class, args); + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/resources/application.properties b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/resources/application.properties new file mode 100644 index 00000000000..0e459353843 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/resources/application.properties @@ -0,0 +1,23 @@ +# +# 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. +# + +kogito.persistence.type=jdbc + +kie.flyway.enabled=true +spring.flyway.enabled=false \ No newline at end of file diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/resources/approval.bpmn b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/resources/approval.bpmn new file mode 100644 index 00000000000..275d148f7ac --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/main/resources/approval.bpmn @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _9EAFE6C1-69B4-4908-B764-EF3C4A55BEE3 + _C13522F1-230A-4C26-B5A9-533A5D9FEE9D + + + + + + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_travellerInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_ActorIdOutputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_approvedOutputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + + + + traveller + _8B62D3CA-5D03-4B2B-832B-126469288BB4_travellerInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_ActorIdOutputX + approver + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_approvedOutputX + firstLineApproval + + + + manager + + + + + + + + + + _C13522F1-230A-4C26-B5A9-533A5D9FEE9D + _078F46FB-B7A1-4DBB-BE9A-75C7CB0CCD03 + + + + + + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_ExcludedOwnerIdInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_travellerInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_approvedOutputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + + + + approver + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_ExcludedOwnerIdInputX + + + traveller + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_travellerInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_approvedOutputX + secondLineApproval + + + + + + + + + _9EAFE6C1-69B4-4908-B764-EF3C4A55BEE3 + + + + + + + + _078F46FB-B7A1-4DBB-BE9A-75C7CB0CCD03 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _F0jB8En5EeqlfsIhq1UCRQ + _F0jB8En5EeqlfsIhq1UCRQ + + diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/BaseUserTaskIT.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/BaseUserTaskIT.java new file mode 100644 index 00000000000..3d8f3075882 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/BaseUserTaskIT.java @@ -0,0 +1,90 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Traveller; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.boot.test.web.server.LocalServerPort; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.emptyOrNullString; + +public abstract class BaseUserTaskIT { + public static final String PROCESS_ID = "approvals"; + public static final String PROCESS_INSTANCE = "approvals/{id}"; + public static final String USER_TASKS_ENDPOINT = "usertasks/instance"; + public static final String USER_TASKS_INSTANCE_ENDPOINT = USER_TASKS_ENDPOINT + "/{taskId}"; + + @LocalServerPort + int httpPort; + + static { + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + } + + @BeforeEach + void setPort() { + RestAssured.port = httpPort; + } + + public String startProcessInstance(Traveller traveller) { + final String pid = given().contentType(ContentType.JSON) + .when() + .body(Map.of("traveller", traveller)) + .post("/{processId}", PROCESS_ID) + .then() + .statusCode(201) + .header("Location", not(emptyOrNullString())) + .body("id", not(emptyOrNullString())) + .extract() + .path("id"); + + given() + .accept(ContentType.JSON) + .when() + .get("/{processId}/{id}", PROCESS_ID, pid) + .then() + .statusCode(200) + .body("id", equalTo(pid)) + .body("traveller.firstName", equalTo(traveller.getFirstName())) + .body("traveller.lastName", equalTo(traveller.getLastName())) + .body("traveller.email", equalTo(traveller.getEmail())) + .body("traveller.nationality", equalTo(traveller.getNationality())); + + return pid; + } + + public void abortProcessInstance(String pid) { + given().contentType(ContentType.JSON) + .when() + .body(Map.of()) + .delete(PROCESS_INSTANCE, pid) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())); + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskAttachmentsIT.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskAttachmentsIT.java new file mode 100644 index 00000000000..60887b11ffb --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskAttachmentsIT.java @@ -0,0 +1,215 @@ +/* + * 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.userTask.jpa.it; + +import java.net.URI; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.it.KogitoSpringbootApplication; +import org.kie.kogito.testcontainers.springboot.PostgreSqlSpringBootTestResource; +import org.kie.kogito.usertask.model.AttachmentInfo; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.emptyOrNullString; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = KogitoSpringbootApplication.class) +@ContextConfiguration(initializers = PostgreSqlSpringBootTestResource.class) +public class UserTaskAttachmentsIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/attachments"; + public static final String USER_TASKS_INSTANCE_ATTACHMENT = USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT + "/{attachmentId}"; + + @Test + public void testUserTaskAttachments() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + final String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + AttachmentInfo attachment1 = new AttachmentInfo(URI.create("http://localhost:8080/attachment_1.txt"), "Attachment 1"); + + String attachment1Id = addAndVerifyAttachment(taskId, attachment1); + + AttachmentInfo attachment2 = new AttachmentInfo(URI.create("http://localhost:8080/attachment_2.txt"), "Attachment 2"); + + String attachment2Id = addAndVerifyAttachment(taskId, attachment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)); + + attachment1 = new AttachmentInfo(URI.create("http://localhost:8080/new_attachment_1.txt"), "NEW Attachment 1"); + + updateAndVerifyAttachment(taskId, attachment1Id, attachment1); + + attachment2 = new AttachmentInfo(URI.create("http://localhost:8080/new_attachment_2.txt"), "NEW Attachment 2"); + + updateAndVerifyAttachment(taskId, attachment2Id, attachment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)) + .body("[0].id", not(emptyOrNullString())) + .body("[0].content", equalTo(attachment1.getUri().toString())) + .body("[0].name", equalTo(attachment1.getName())) + .body("[0].updatedBy", not(emptyOrNullString())) + .body("[0].updatedAt", not(emptyOrNullString())) + .body("[1].id", not(emptyOrNullString())) + .body("[1].content", equalTo(attachment2.getUri().toString())) + .body("[1].name", equalTo(attachment2.getName())) + .body("[1].updatedBy", not(emptyOrNullString())) + .body("[1].updatedAt", not(emptyOrNullString())); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachment1Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(1)); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachment2Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + abortProcessInstance(pid); + } + + private String addAndVerifyAttachment(String taskId, AttachmentInfo attachment) { + String id = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(attachment) + .post(USER_TASKS_INSTANCE_ATTACHMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENT, taskId, id) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + + return id; + } + + private void updateAndVerifyAttachment(String taskId, String attachmentId, AttachmentInfo attachment) { + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(attachment) + .put(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachmentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ATTACHMENT, taskId, attachmentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(attachment.getUri().toString())) + .body("name", equalTo(attachment.getName())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskCommentsIT.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskCommentsIT.java new file mode 100644 index 00000000000..07f7f91c4ac --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskCommentsIT.java @@ -0,0 +1,207 @@ +/* + * 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.userTask.jpa.it; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.it.KogitoSpringbootApplication; +import org.kie.kogito.testcontainers.springboot.PostgreSqlSpringBootTestResource; +import org.kie.kogito.usertask.model.CommentInfo; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.emptyOrNullString; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = KogitoSpringbootApplication.class) +@ContextConfiguration(initializers = PostgreSqlSpringBootTestResource.class) +public class UserTaskCommentsIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_COMMENTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/comments"; + public static final String USER_TASKS_INSTANCE_COMMENT = USER_TASKS_INSTANCE_COMMENTS_ENDPOINT + "/{commentId}"; + + @Test + public void testUserTaskComments() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + final String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + CommentInfo comment1 = new CommentInfo("This is my second comment."); + + String comment1Id = addAndVerifyComment(taskId, comment1); + + CommentInfo comment2 = new CommentInfo("This is my second comment."); + + String comment2Id = addAndVerifyComment(taskId, comment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)); + + comment1 = new CommentInfo("This is the first comment modified"); + + updateAndVerifyComment(taskId, comment1Id, comment1); + + comment2 = new CommentInfo("This is the second comment modified"); + + updateAndVerifyComment(taskId, comment2Id, comment2); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(2)) + .body("[0].id", not(emptyOrNullString())) + .body("[0].content", equalTo(comment1.getComment())) + .body("[0].updatedBy", not(emptyOrNullString())) + .body("[0].updatedAt", not(emptyOrNullString())) + .body("[1].id", not(emptyOrNullString())) + .body("[1].content", equalTo(comment2.getComment())) + .body("[1].updatedBy", not(emptyOrNullString())) + .body("[1].updatedAt", not(emptyOrNullString())); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_COMMENT, taskId, comment1Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(1)); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .delete(USER_TASKS_INSTANCE_COMMENT, taskId, comment2Id) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + abortProcessInstance(pid); + } + + private String addAndVerifyComment(String taskId, CommentInfo comment) { + String id = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(comment) + .post(USER_TASKS_INSTANCE_COMMENTS_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENT, taskId, id) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + + return id; + } + + private void updateAndVerifyComment(String taskId, String commentId, CommentInfo comment) { + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(comment) + .put(USER_TASKS_INSTANCE_COMMENT, taskId, commentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())) + .extract() + .path("id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_COMMENT, taskId, commentId) + .then() + .statusCode(200) + .body("id", not(emptyOrNullString())) + .body("content", equalTo(comment.getComment())) + .body("updatedBy", not(emptyOrNullString())) + .body("updatedAt", not(emptyOrNullString())); + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskInputs.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskInputs.java new file mode 100644 index 00000000000..0357f040233 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskInputs.java @@ -0,0 +1,110 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.it.KogitoSpringbootApplication; +import org.kie.kogito.testcontainers.springboot.PostgreSqlSpringBootTestResource; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = KogitoSpringbootApplication.class) +@ContextConfiguration(initializers = PostgreSqlSpringBootTestResource.class) +public class UserTaskInputs extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_INPUTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/inputs"; + + @Test + public void testUserTaskInputs() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")) + .body("taskName", equalTo("firstLineApproval")) + .body("potentialUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + Traveller newTraveller = new Traveller("Ned", "Stark", "n.stark@winterfell.com", "Northern", new Address("main street", "Winterfell", "10005", "WF")); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(Map.of("traveller", newTraveller)) + .put(USER_TASKS_INSTANCE_INPUTS_ENDPOINT, taskId) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("inputs.traveller.firstName", equalTo(newTraveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(newTraveller.getLastName())) + .body("inputs.traveller.email", equalTo(newTraveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(newTraveller.getNationality())) + .body("inputs.traveller.address.street", equalTo(newTraveller.getAddress().getStreet())) + .body("inputs.traveller.address.city", equalTo(newTraveller.getAddress().getCity())) + .body("inputs.traveller.address.zipCode", equalTo(newTraveller.getAddress().getZipCode())) + .body("inputs.traveller.address.country", equalTo(newTraveller.getAddress().getCountry())); + + abortProcessInstance(pid); + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskLifeCycleIT.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskLifeCycleIT.java new file mode 100644 index 00000000000..0f04acf9565 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskLifeCycleIT.java @@ -0,0 +1,196 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.it.KogitoSpringbootApplication; +import org.kie.kogito.testcontainers.springboot.PostgreSqlSpringBootTestResource; +import org.kie.kogito.usertask.model.TransitionInfo; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = KogitoSpringbootApplication.class) +@ContextConfiguration(initializers = PostgreSqlSpringBootTestResource.class) +public class UserTaskLifeCycleIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_TRANSITION_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/transition"; + + @Test + public void testUserTaskLifeCycle() { + + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + final String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")) + .body("taskName", equalTo("firstLineApproval")) + .body("potentialUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + given() + .contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(new TransitionInfo("complete", Map.of("approved", true))) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Completed")) + .body("status.terminate", equalTo("COMPLETED")) + .body("outputs.approved", equalTo(true)); + + // Manager is excluded for the secondLineApproval Task, he shouldn't be allowed to see the task + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(0)); + + taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .body("[0].id", not(taskId)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Ready")) + .body("taskName", equalTo("secondLineApproval")) + .body("excludedUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + // Manager is excluded for the secondLineApproval Task, he shouldn't be able to work on the task + given() + .contentType(ContentType.JSON) + .when() + .body(Map.of()) + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(new TransitionInfo("claim")) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(500); + + given() + .contentType(ContentType.JSON) + .when() + .body(Map.of()) + .queryParam("user", "john") + .queryParam("group", "managers") + .body(new TransitionInfo("claim")) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")); + + given() + .contentType(ContentType.JSON) + .when() + .queryParam("user", "john") + .queryParam("group", "managers") + .body(new TransitionInfo("complete", Map.of("approved", true))) + .post(USER_TASKS_INSTANCE_TRANSITION_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Completed")) + .body("status.terminate", equalTo("COMPLETED")) + .body("outputs.approved", equalTo(true)); + + given() + .accept(ContentType.JSON) + .when() + .get("/{processId}/{id}", PROCESS_ID, pid) + .then() + .statusCode(404); + } +} diff --git a/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskOutputsIT.java b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskOutputsIT.java new file mode 100644 index 00000000000..b89e19989a1 --- /dev/null +++ b/springboot/integration-tests/integration-tests-springboot-usertasks-it/src/test/java/org/jbpm/userTask/jpa/it/UserTaskOutputsIT.java @@ -0,0 +1,112 @@ +/* + * 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.userTask.jpa.it; + +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.junit.jupiter.api.Test; +import org.kie.kogito.it.KogitoSpringbootApplication; +import org.kie.kogito.testcontainers.springboot.PostgreSqlSpringBootTestResource; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = KogitoSpringbootApplication.class) +@ContextConfiguration(initializers = PostgreSqlSpringBootTestResource.class) +public class UserTaskOutputsIT extends BaseUserTaskIT { + public static final String USER_TASKS_INSTANCE_OUTPUTS_ENDPOINT = USER_TASKS_INSTANCE_ENDPOINT + "/outputs"; + + @Test + public void testUserTaskOutputs() { + Traveller traveller = new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US")); + + String pid = startProcessInstance(traveller); + + String taskId = given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_ENDPOINT) + .then() + .statusCode(200) + .body("$.size()", is(1)) + .extract() + .path("[0].id"); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("status.name", equalTo("Reserved")) + .body("taskName", equalTo("firstLineApproval")) + .body("potentialUsers", hasItem("manager")) + .body("potentialGroups", hasItem("managers")) + .body("inputs.traveller.firstName", equalTo(traveller.getFirstName())) + .body("inputs.traveller.lastName", equalTo(traveller.getLastName())) + .body("inputs.traveller.email", equalTo(traveller.getEmail())) + .body("inputs.traveller.nationality", equalTo(traveller.getNationality())) + .body("metadata.ProcessType", equalTo("BPMN")) + .body("metadata.ProcessVersion", equalTo("1.0")) + .body("metadata.ProcessId", equalTo(PROCESS_ID)) + .body("metadata.ProcessInstanceId", equalTo(pid)) + .body("metadata.ProcessInstanceState", equalTo(1)); + + Traveller newTraveller = new Traveller("Ned", "Stark", "n.stark@winterfell.com", "Northern", new Address("main street", "Winterfell", "10005", "WF")); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .body(Map.of("traveller", newTraveller, "approved", true)) + .put(USER_TASKS_INSTANCE_OUTPUTS_ENDPOINT, taskId) + .then() + .statusCode(200); + + given().contentType(ContentType.JSON) + .when() + .queryParam("user", "manager") + .queryParam("group", "department-managers") + .get(USER_TASKS_INSTANCE_ENDPOINT, taskId) + .then() + .statusCode(200) + .body("id", equalTo(taskId)) + .body("outputs.approved", is(true)) + .body("outputs.traveller.firstName", equalTo(newTraveller.getFirstName())) + .body("outputs.traveller.lastName", equalTo(newTraveller.getLastName())) + .body("outputs.traveller.email", equalTo(newTraveller.getEmail())) + .body("outputs.traveller.nationality", equalTo(newTraveller.getNationality())) + .body("outputs.traveller.address.street", equalTo(newTraveller.getAddress().getStreet())) + .body("outputs.traveller.address.city", equalTo(newTraveller.getAddress().getCity())) + .body("outputs.traveller.address.zipCode", equalTo(newTraveller.getAddress().getZipCode())) + .body("outputs.traveller.address.country", equalTo(newTraveller.getAddress().getCountry())); + + abortProcessInstance(pid); + } +} diff --git a/springboot/integration-tests/pom.xml b/springboot/integration-tests/pom.xml index 4bf6bb95a02..4e76b109677 100644 --- a/springboot/integration-tests/pom.xml +++ b/springboot/integration-tests/pom.xml @@ -41,6 +41,7 @@ integration-tests-springboot-norest-it integration-tests-springboot-processes-it integration-tests-springboot-processes-persistence-it + integration-tests-springboot-usertasks-it