diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0b20367bb45..ccc348d4f9c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -46,8 +46,8 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -55,14 +55,14 @@ jobs: ${{ runner.os }}-maven- - name: Set up JDK 21 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0 with: java-version: '21' distribution: 'temurin' # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 + uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # v3.26.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -98,6 +98,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 + uses: github/codeql-action/analyze@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # v3.26.5 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/create-github-prerelease.yaml b/.github/workflows/create-github-prerelease.yaml index 02504993e50..4cc3f00cba1 100644 --- a/.github/workflows/create-github-prerelease.yaml +++ b/.github/workflows/create-github-prerelease.yaml @@ -9,7 +9,7 @@ jobs: create-prerelease: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Resolve activiti version id: resolve-versions run: | @@ -20,13 +20,13 @@ jobs: - run: touch release.yaml - - uses: Alfresco/alfresco-build-tools/.github/actions/update-project-base-tag@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/update-project-base-tag@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: release-descriptor: release.yaml project: activiti tag: ${{ steps.resolve-versions.outputs.activiti-tag }} - - uses: Alfresco/alfresco-build-tools/.github/actions/update-project-base-tag@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/update-project-base-tag@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: release-descriptor: release.yaml project: activitiCloud diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cde26eeae61..a6014f530e9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,15 +28,15 @@ jobs: pre-checks: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Check dependabot build - uses: Activiti/Activiti/.github/actions/check-ext-build@4db084fcbb13a288f3b66ac08fc50a5ab7f144ed # 8.0.0-alpha.10 + uses: Activiti/Activiti/.github/actions/check-ext-build@7700f0283a9ff5181581a350d2520e55c61c1c60 # 8.6.0 - name: pre-commit - uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: skip_checkout: true - name: Ensure SHA pinned actions - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@ba37328d4ea95eaf8b3bd6c6cef308f709a5f2ec # v3.0.3 + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@40ba2d51b6b6d8695f2b6bd74e785172d4f8d00f # v3.0.14 build: runs-on: ubuntu-latest @@ -48,11 +48,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: token: ${{ secrets.BOT_GITHUB_TOKEN }} - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -60,7 +60,7 @@ jobs: ${{ runner.os }}-maven- - name: Setup Java JDK 21 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # 4.2.1 + uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # 4.4.0 with: java-version: 21 distribution: 'temurin' @@ -72,7 +72,7 @@ jobs: GITHUB_PR_NUMBER=PR-${{ github.event.pull_request.number }} echo "version=0.0.1-${GITHUB_PR_NUMBER}-SNAPSHOT" >> $GITHUB_OUTPUT - - uses: Alfresco/alfresco-build-tools/.github/actions/update-pom-to-next-pre-release@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/update-pom-to-next-pre-release@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 id: update-pom-to-next-version with: version: ${{ steps.resolve-override-version.outputs.version }} @@ -104,7 +104,7 @@ jobs: run: find . -name TEST-*.xml -exec grep -h testcase {} \; | awk -F '"' '{printf("%s#%s() - %.3fms\n", $4, $2, $6); }' | sort -n -k 3 | tail -20 - name: Login to DockerHub - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} @@ -128,7 +128,9 @@ jobs: env: MAVEN_CLI_OPTS: --show-version --no-transfer-progress --settings settings.xml strategy: - fail-fast: false + # avoid overloading test cluster + max-parallel: 2 + fail-fast: true matrix: messaging-broker: [ rabbitmq, kafka ] messaging-partitioned: [ partitioned, non-partitioned ] @@ -139,9 +141,9 @@ jobs: messaging-destinations: override-destinations steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -149,7 +151,7 @@ jobs: ${{ runner.os }}-maven- - name: Setup Java JDK 21 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # 4.2.1 + uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # 4.4.0 with: java-version: 21 distribution: 'temurin' @@ -160,12 +162,12 @@ jobs: version: v1.19.6 - name: Set up Helm - uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3 + uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v3 with: version: v3.5.2 - name: Set up rancher - uses: Alfresco/alfresco-build-tools/.github/actions/setup-rancher-cli@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + uses: Alfresco/alfresco-build-tools/.github/actions/setup-rancher-cli@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: url: ${{ secrets.RANCHER2_URL }} access-key: ${{ secrets.RANCHER2_ACCESS_KEY }} @@ -277,16 +279,9 @@ jobs: - name: Delete Helm chart for ${{ matrix.messaging-broker }} if: always() - env: - IS_PREVIEW: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'preview') }} run: | - if [ $IS_PREVIEW = true ] - then - echo "Skipping delete Helm release for preview" - else - echo "Delete Helm release" - make delete - fi + echo "Delete Helm release" + make delete delete-test-images: runs-on: ubuntu-latest @@ -296,7 +291,7 @@ jobs: - build steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Delete Docker images env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} @@ -324,17 +319,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: token: ${{ secrets.BOT_GITHUB_TOKEN }} - name: Setup Java JDK 21 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4.4.0 with: java-version: 21 distribution: 'temurin' - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -353,7 +348,7 @@ jobs: MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }} MAVEN_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} - - uses: Alfresco/alfresco-build-tools/.github/actions/git-commit-changes@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/git-commit-changes@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: username: ${{ secrets.BOT_GITHUB_USERNAME }} add-options: -u @@ -375,8 +370,8 @@ jobs: VERSION: ${{ needs.build.outputs.version }} DEVELOPMENT_BRANCH: ${{ github.ref_name }} steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - - uses: Alfresco/alfresco-build-tools/.github/actions/jx-updatebot-pr@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: Alfresco/alfresco-build-tools/.github/actions/jx-updatebot-pr@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: version: ${{ needs.build.outputs.version }} auto-merge: 'true' @@ -398,7 +393,7 @@ jobs: FULL_CHART_BASE_BRANCH: develop FULL_CHART_PR_BRANCH: update-docker-images-${{ needs.build.outputs.version }} steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: path: ${{ env.FULL_CHART_DIR }} repository: Activiti/activiti-cloud-full-chart @@ -413,12 +408,12 @@ jobs: yq -i e '.activiti-cloud-connector.image.tag = env(VERSION)' values.yaml yq -i e '.activiti-cloud-identity-adapter.image.tag = env(VERSION)' values.yaml - - uses: Alfresco/alfresco-build-tools/.github/actions/setup-helm-docs@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/setup-helm-docs@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 - name: Update helm docs working-directory: ${{ env.FULL_CHART_DIR}} run: helm-docs - - uses: Alfresco/alfresco-build-tools/.github/actions/git-commit-changes@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/git-commit-changes@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: username: ${{ secrets.BOT_GITHUB_USERNAME }} add-options: -u @@ -441,7 +436,7 @@ jobs: if: always() && failure() && github.event_name == 'push' steps: - name: Slack Notification - uses: Alfresco/alfresco-build-tools/.github/actions/send-slack-notification@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + uses: Alfresco/alfresco-build-tools/.github/actions/send-slack-notification@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: - channel-id: 'eng-hxp-studio-activiti-gh-notifs' + channel-id: 'C03PMT6APFU' # eng-hxp-studio-activiti-gh-notifs, to be renamed eng-automate-activiti-gh-notifs token: ${{ secrets.SLACK_NOTIFICATION_BOT_TOKEN }} diff --git a/.github/workflows/pr-closed.yaml b/.github/workflows/pr-closed.yaml index 52701328693..a9951ba0a96 100644 --- a/.github/workflows/pr-closed.yaml +++ b/.github/workflows/pr-closed.yaml @@ -26,7 +26,7 @@ jobs: version: v1.19.6 - name: Set up rancher - uses: Alfresco/alfresco-build-tools/.github/actions/setup-rancher-cli@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + uses: Alfresco/alfresco-build-tools/.github/actions/setup-rancher-cli@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: url: ${{ secrets.RANCHER2_URL }} access-key: ${{ secrets.RANCHER2_ACCESS_KEY }} @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set PREVIEW_NAME env variable id: set-preview-name diff --git a/.github/workflows/versions-propagation-auto-merge.yml b/.github/workflows/versions-propagation-auto-merge.yml index 802ba62ab19..ec93ec6be59 100644 --- a/.github/workflows/versions-propagation-auto-merge.yml +++ b/.github/workflows/versions-propagation-auto-merge.yml @@ -9,7 +9,7 @@ jobs: versions-propagation-auto-merge: runs-on: ubuntu-latest steps: - - uses: Alfresco/alfresco-build-tools/.github/actions/automate-propagation@a3f5a4ae53302e9a1f9dc728dee0f4069c1bc584 # v5.22.1 + - uses: Alfresco/alfresco-build-tools/.github/actions/automate-propagation@209bb4275688720e13dc0703dbd17826bf677c5c # v6.1.0 with: auto-merge-token: ${{ secrets.BOT_GITHUB_TOKEN }} approval-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.jx/updatebot.yaml b/.jx/updatebot.yaml index 88185e455ba..2174fdc280f 100644 --- a/.jx/updatebot.yaml +++ b/.jx/updatebot.yaml @@ -3,8 +3,7 @@ kind: UpdateConfig spec: rules: - urls: - - https://github.com/Alfresco/alfresco-process - - https://github.com/Alfresco/alfresco-process-sdk + - https://github.com/Alfresco/hxp-process-services reusePullRequest: true changes: - regex: diff --git a/activiti-cloud-acceptance-scenarios/identity-adapter-acceptance-tests/pom.xml b/activiti-cloud-acceptance-scenarios/identity-adapter-acceptance-tests/pom.xml index f8245e4be59..3835fbf07e9 100644 --- a/activiti-cloud-acceptance-scenarios/identity-adapter-acceptance-tests/pom.xml +++ b/activiti-cloud-acceptance-scenarios/identity-adapter-acceptance-tests/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-acceptance-scenarios-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT identity-adapter-acceptance-tests Activiti Cloud :: Acceptance Scenarios Identity Adapter diff --git a/activiti-cloud-acceptance-scenarios/multiple-runtime-acceptance-tests/pom.xml b/activiti-cloud-acceptance-scenarios/multiple-runtime-acceptance-tests/pom.xml index 8ce29e3268e..7157f09919f 100644 --- a/activiti-cloud-acceptance-scenarios/multiple-runtime-acceptance-tests/pom.xml +++ b/activiti-cloud-acceptance-scenarios/multiple-runtime-acceptance-tests/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-acceptance-scenarios-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT multiple-runtime-acceptance-tests Activiti Cloud :: Acceptance Scenarios Multi-Runtime diff --git a/activiti-cloud-acceptance-scenarios/pom.xml b/activiti-cloud-acceptance-scenarios/pom.xml index f61f9b74daa..19fd5c6acb6 100644 --- a/activiti-cloud-acceptance-scenarios/pom.xml +++ b/activiti-cloud-acceptance-scenarios/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-acceptance-scenarios-parent diff --git a/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/pom.xml b/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/pom.xml index 8aee6105e38..faa4b1514f6 100644 --- a/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/pom.xml +++ b/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-acceptance-scenarios-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT runtime-acceptance-tests Activiti Cloud :: Acceptance Scenarios Runtime diff --git a/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/java/org/activiti/cloud/qa/story/ProcessInstanceTasks.java b/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/java/org/activiti/cloud/qa/story/ProcessInstanceTasks.java index a24da352b38..22a25edcbfe 100644 --- a/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/java/org/activiti/cloud/qa/story/ProcessInstanceTasks.java +++ b/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/java/org/activiti/cloud/qa/story/ProcessInstanceTasks.java @@ -404,6 +404,11 @@ public void adminDeleteCurrentProcessInstance() throws Exception { processRuntimeAdminSteps.deleteProcessInstance(processInstance.getId()); } + @When("the admin force destroys the process") + public void adminForceDeleteCurrentProcessInstance() throws Exception { + processRuntimeAdminSteps.destroyProcessInstance(processInstance.getId(), true); + } + @When("the user suspends the process instance") public void suspendProcessInstance() throws Exception { processRuntimeBundleSteps.suspendProcessInstance(processInstance.getId()); @@ -423,6 +428,16 @@ public void verifyProcessInstanceIsDeleted() throws Exception { ); } + @Then("the process instance is destroyed") + public void verifyProcessInstanceIsForceDestroyed() throws Exception { + processRuntimeBundleSteps.checkProcessInstanceNotFound(processInstance.getId()); + processQuerySteps.checkProcessInstanceNotFound(processInstance.getId()); + auditSteps.checkProcessInstanceEvent( + processInstance.getId(), + ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED + ); + } + @When("open the process diagram") public void openProcessInstanceDiagram() { processInstanceDiagram = processRuntimeBundleSteps.openProcessInstanceDiagram(processInstance.getId()); diff --git a/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/resources/stories/runtime-bundle/process-instance-actions.story b/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/resources/stories/runtime-bundle/process-instance-actions.story index f0bf0bfff8a..587f02d5e47 100644 --- a/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/resources/stories/runtime-bundle/process-instance-actions.story +++ b/activiti-cloud-acceptance-scenarios/runtime-acceptance-tests/src/main/resources/stories/runtime-bundle/process-instance-actions.story @@ -120,6 +120,12 @@ When the user starts an instance of the process called PROCESS_INSTANCE_WITH_VAR And the admin deletes the process Then the process instance is deleted +Scenario: admin force destroy a process instance +Given the user is authenticated as testadmin +When the user starts an instance of the process called PROCESS_INSTANCE_WITH_VARIABLES +And the admin force destroys the process +Then the process instance is destroyed + Scenario: check sequence number and message id for events Given the user is authenticated as testuser When the user starts an instance of the process called SIMPLE_PROCESS_INSTANCE diff --git a/activiti-cloud-acceptance-scenarios/security-policies-acceptance-tests/pom.xml b/activiti-cloud-acceptance-scenarios/security-policies-acceptance-tests/pom.xml index 42e3d3b6f4a..7a9feef1547 100644 --- a/activiti-cloud-acceptance-scenarios/security-policies-acceptance-tests/pom.xml +++ b/activiti-cloud-acceptance-scenarios/security-policies-acceptance-tests/pom.xml @@ -4,7 +4,7 @@ org.activiti.cloud activiti-cloud-acceptance-scenarios-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT 4.0.0 security-policies-acceptance-tests diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/pom.xml b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/pom.xml index 735e5960315..5dd059b865f 100644 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/pom.xml +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-acceptance-tests-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-acceptance-tests-dependencies activiti-cloud-acceptance-tests-core diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/assertions/RestErrorAssert.java b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/assertions/RestErrorAssert.java index 477fc0d097b..d3eaafa1652 100644 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/assertions/RestErrorAssert.java +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/assertions/RestErrorAssert.java @@ -15,7 +15,8 @@ */ package org.activiti.cloud.acc.core.assertions; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; import feign.FeignException; import jakarta.servlet.http.HttpServletResponse; diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/services/runtime/admin/ProcessRuntimeAdminService.java b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/services/runtime/admin/ProcessRuntimeAdminService.java index 88f08ea2ff1..0311ef09359 100644 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/services/runtime/admin/ProcessRuntimeAdminService.java +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/services/runtime/admin/ProcessRuntimeAdminService.java @@ -31,6 +31,9 @@ public interface ProcessRuntimeAdminService { @RequestLine("DELETE /admin/v1/process-instances/{id}") void deleteProcess(@Param("id") String id); + @RequestLine("DELETE /admin/v1/process-instances/{id}/destroy?force={force}") + void destroyProcess(@Param("id") String id, @Param("force") boolean force); + @RequestLine("POST /admin/v1/process-instances/message") @Headers("Content-Type: application/json") CloudProcessInstance message(StartMessagePayload startProcess); diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/query/ProcessQuerySteps.java b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/query/ProcessQuerySteps.java index 900d61a5b5a..ea7104c4a88 100644 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/query/ProcessQuerySteps.java +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/query/ProcessQuerySteps.java @@ -15,6 +15,7 @@ */ package org.activiti.cloud.acc.core.steps.query; +import static org.activiti.cloud.acc.core.assertions.RestErrorAssert.assertThatRestNotFoundErrorIsThrownBy; import static org.activiti.cloud.services.common.util.ImageUtils.svgToPng; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @@ -174,4 +175,13 @@ public void checkProcessInstanceDiagram(String diagram) throws Exception { public void checkProcessInstanceNoDiagram(String diagram) { assertThat(diagram).isEmpty(); } + + @Step + public void checkProcessInstanceNotFound(String processInstanceId) { + await() + .pollInSameThread() + .untilAsserted(() -> + assertThatRestNotFoundErrorIsThrownBy(() -> processQueryService.getProcessInstance(processInstanceId)) + ); + } } diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/runtime/admin/ProcessRuntimeAdminSteps.java b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/runtime/admin/ProcessRuntimeAdminSteps.java index 505577ce4cd..bb914ff59d8 100644 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/runtime/admin/ProcessRuntimeAdminSteps.java +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-core/src/main/java/org/activiti/cloud/acc/core/steps/runtime/admin/ProcessRuntimeAdminSteps.java @@ -54,6 +54,11 @@ public void deleteProcessInstance(String id) { processRuntimeAdminService.deleteProcess(id); } + @Step + public void destroyProcessInstance(String id, boolean force) { + processRuntimeAdminService.destroyProcess(id, force); + } + @Step public CloudProcessInstance message(StartMessagePayload payload) throws IOException { return processRuntimeAdminService.message(payload); diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-dependencies/pom.xml b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-dependencies/pom.xml index 779ae8bff53..ab605cb35d3 100755 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-dependencies/pom.xml +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-acceptance-tests-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-acceptance-tests-dependencies pom diff --git a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-shared/pom.xml b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-shared/pom.xml index 978da794693..871b921e285 100644 --- a/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-shared/pom.xml +++ b/activiti-cloud-acceptance-tests/activiti-cloud-acceptance-tests-shared/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-acceptance-tests-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-acceptance-tests-dependencies activiti-cloud-acceptance-tests-shared diff --git a/activiti-cloud-acceptance-tests/pom.xml b/activiti-cloud-acceptance-tests/pom.xml index f5a327f01d2..ccda295843a 100644 --- a/activiti-cloud-acceptance-tests/pom.xml +++ b/activiti-cloud-acceptance-tests/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-acceptance-tests-parent @@ -84,6 +84,11 @@ batik-codec ${batik.version} + + io.github.classgraph + classgraph + ${classgraph.version} + diff --git a/activiti-cloud-api/activiti-cloud-api-dependencies/pom.xml b/activiti-cloud-api/activiti-cloud-api-dependencies/pom.xml index 440343b3022..ef09637a49c 100755 --- a/activiti-cloud-api/activiti-cloud-api-dependencies/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-api-dependencies pom diff --git a/activiti-cloud-api/activiti-cloud-api-events/pom.xml b/activiti-cloud-api/activiti-cloud-api-events/pom.xml index 597cf554b29..df06f6274d7 100644 --- a/activiti-cloud-api/activiti-cloud-api-events/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-events/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-events diff --git a/activiti-cloud-api/activiti-cloud-api-model-shared-impl/pom.xml b/activiti-cloud-api/activiti-cloud-api-model-shared-impl/pom.xml index edd82c32b67..2abafc12c93 100644 --- a/activiti-cloud-api/activiti-cloud-api-model-shared-impl/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-model-shared-impl/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-model-shared-impl diff --git a/activiti-cloud-api/activiti-cloud-api-model-shared/pom.xml b/activiti-cloud-api/activiti-cloud-api-model-shared/pom.xml index 75a6ac7babd..11b23d9b08c 100644 --- a/activiti-cloud-api/activiti-cloud-api-model-shared/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-model-shared/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-model-shared diff --git a/activiti-cloud-api/activiti-cloud-api-process-model-impl/pom.xml b/activiti-cloud-api/activiti-cloud-api-process-model-impl/pom.xml index 895ce329f85..87365a8822c 100644 --- a/activiti-cloud-api/activiti-cloud-api-process-model-impl/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-process-model-impl/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-process-model-impl diff --git a/activiti-cloud-api/activiti-cloud-api-process-model/pom.xml b/activiti-cloud-api/activiti-cloud-api-process-model/pom.xml index 4df31489eb0..9c15e55b96b 100644 --- a/activiti-cloud-api/activiti-cloud-api-process-model/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-process-model/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-process-model diff --git a/activiti-cloud-api/activiti-cloud-api-task-model-impl/pom.xml b/activiti-cloud-api/activiti-cloud-api-task-model-impl/pom.xml index ead6c58cf52..9edfd5712c0 100644 --- a/activiti-cloud-api/activiti-cloud-api-task-model-impl/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-task-model-impl/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-task-model-impl diff --git a/activiti-cloud-api/activiti-cloud-api-task-model/pom.xml b/activiti-cloud-api/activiti-cloud-api-task-model/pom.xml index d59d82062f3..674b060e755 100644 --- a/activiti-cloud-api/activiti-cloud-api-task-model/pom.xml +++ b/activiti-cloud-api/activiti-cloud-api-task-model/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-api-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-api-dependencies activiti-cloud-api-task-model diff --git a/activiti-cloud-api/pom.xml b/activiti-cloud-api/pom.xml index 2dca397091f..5979ac9859b 100644 --- a/activiti-cloud-api/pom.xml +++ b/activiti-cloud-api/pom.xml @@ -5,14 +5,14 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-api Activiti Cloud :: Runtime API Parent pom - 8.5.0-alpha.4 + 8.7.0-alpha.27 activiti-cloud-api-dependencies diff --git a/activiti-cloud-audit-service/activiti-cloud-audit-dependencies/pom.xml b/activiti-cloud-audit-service/activiti-cloud-audit-dependencies/pom.xml index a78153b18d0..ea778e833a5 100755 --- a/activiti-cloud-audit-service/activiti-cloud-audit-dependencies/pom.xml +++ b/activiti-cloud-audit-service/activiti-cloud-audit-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-audit-service-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-audit-dependencies pom @@ -20,6 +20,11 @@ activiti-cloud-services-audit-parent ${project.version} + + org.activiti.cloud + activiti-cloud-services-audit-consumer + ${project.version} + org.activiti.cloud activiti-cloud-services-audit-model @@ -27,7 +32,7 @@ org.activiti.cloud - activiti-cloud-services-audit-jpa + activiti-cloud-services-audit-rest ${project.version} @@ -40,6 +45,16 @@ activiti-cloud-services-audit-liquibase ${project.version} + + org.activiti.cloud + activiti-cloud-starter-audit-rest + ${project.version} + + + org.activiti.cloud + activiti-cloud-starter-audit-consumer + ${project.version} + org.activiti.cloud activiti-cloud-starter-audit @@ -94,6 +109,11 @@ ${querydsl.version} jakarta + + io.github.classgraph + classgraph + ${classgraph.version} + diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/pom.xml b/activiti-cloud-audit-service/activiti-cloud-services-audit-api/pom.xml index 4b512c7e0bc..d25d050cf8b 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/pom.xml +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-api/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-audit-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-audit-dependencies activiti-cloud-services-audit-api @@ -23,10 +23,6 @@ org.activiti.cloud activiti-cloud-api-process-model-impl - - org.activiti.cloud - activiti-cloud-service-messaging-config - org.activiti.cloud activiti-cloud-services-dbp-rest @@ -60,14 +56,6 @@ spring-boot-autoconfigure true - - org.springframework - spring-messaging - - - org.springframework.cloud - spring-cloud-stream - com.fasterxml.jackson.core jackson-annotations diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/config/AuditAPIAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/config/AuditAPIAutoConfiguration.java index bd450c1b69c..0ef1a684e26 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/config/AuditAPIAutoConfiguration.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/config/AuditAPIAutoConfiguration.java @@ -18,10 +18,8 @@ import org.activiti.cloud.services.audit.api.resources.EventsLinkRelationProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; @AutoConfiguration -@Import(AuditConsumerChannelsConfiguration.class) public class AuditAPIAutoConfiguration { @Bean diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/pom.xml b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/pom.xml new file mode 100644 index 00000000000..a0f1397521c --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-audit-dependencies + 8.7.0-SNAPSHOT + ../activiti-cloud-audit-dependencies + + activiti-cloud-services-audit-consumer + Activiti Cloud Audit :: Services :: Audit Events Consumer + + + + + + org.activiti.cloud + activiti-cloud-api-model-shared + + + org.activiti.cloud + activiti-cloud-service-messaging-config + + + org.activiti.cloud + activiti-cloud-services-audit-model + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.cloud + spring-cloud-starter-stream-rabbit + test + + + diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/config/AuditJPAControllersAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsAutoConfiguration.java similarity index 60% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/config/AuditJPAControllersAutoConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsAutoConfiguration.java index 295390f5bc0..b7b4bf5de00 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/config/AuditJPAControllersAutoConfiguration.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsAutoConfiguration.java @@ -13,14 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.activiti.cloud.services.audit.jpa.controllers.config; +package org.activiti.cloud.services.audit.api.config; -import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsAdminControllerImpl; -import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsControllerImpl; -import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsDeleteController; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Import; @AutoConfiguration -@Import({ AuditEventsAdminControllerImpl.class, AuditEventsControllerImpl.class, AuditEventsDeleteController.class }) -public class AuditJPAControllersAutoConfiguration {} +@Import(AuditConsumerChannelsConfiguration.class) +public class AuditConsumerChannelsAutoConfiguration {} diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsConfiguration.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/config/AuditConsumerChannelsConfiguration.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannelHandler.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannelHandler.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannelHandler.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannelHandler.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannels.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannels.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannels.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/api/streams/AuditConsumerChannels.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImpl.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImpl.java similarity index 97% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImpl.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImpl.java index ea04ca99d8f..e36d12b2927 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImpl.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImpl.java @@ -24,7 +24,6 @@ import org.activiti.cloud.services.audit.api.converters.APIEventToEntityConverters; import org.activiti.cloud.services.audit.api.converters.EventToEntityConverter; import org.activiti.cloud.services.audit.api.streams.AuditConsumerChannelHandler; -import org.activiti.cloud.services.audit.api.streams.AuditConsumerChannels; import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; import org.slf4j.Logger; diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/streams/config/AuditJPAStreamsAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/jpa/streams/config/AuditJPAStreamsAutoConfiguration.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/streams/config/AuditJPAStreamsAutoConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/java/org/activiti/cloud/services/audit/jpa/streams/config/AuditJPAStreamsAutoConfiguration.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..0a2e7ec041e --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +org.activiti.cloud.services.audit.api.config.AuditConsumerChannelsAutoConfiguration +org.activiti.cloud.services.audit.jpa.streams.config.AuditJPAStreamsAutoConfiguration diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImplTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/test/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImplTest.java similarity index 64% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImplTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/test/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImplTest.java index 0d2f1ea8b9f..1962c754c2b 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImplTest.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-consumer/src/test/java/org/activiti/cloud/services/audit/jpa/streams/AuditConsumerChannelHandlerImplTest.java @@ -15,9 +15,6 @@ */ package org.activiti.cloud.services.audit.jpa.streams; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - import java.util.HashMap; import java.util.UUID; import org.activiti.api.process.model.events.ProcessRuntimeEvent; @@ -28,12 +25,14 @@ import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; import org.activiti.cloud.services.audit.jpa.events.ProcessCreatedAuditEventEntity; import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) @@ -54,13 +53,14 @@ public class AuditConsumerChannelHandlerImplTest { @Test public void receiveEventShouldStoreEntity() { //given - CloudRuntimeEvent cloudRuntimeEvent = mock(CloudRuntimeEventImpl.class); - when(cloudRuntimeEvent.getEventType()).thenReturn(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED); - EventToEntityConverter converter = mock(EventToEntityConverter.class); - when(converters.getConverterByEventTypeName(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name())) + CloudRuntimeEvent cloudRuntimeEvent = Mockito.mock(CloudRuntimeEventImpl.class); + Mockito.when(cloudRuntimeEvent.getEventType()).thenReturn(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED); + EventToEntityConverter converter = Mockito.mock(EventToEntityConverter.class); + Mockito + .when(converters.getConverterByEventTypeName(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name())) .thenReturn(converter); - ProcessCreatedAuditEventEntity entity = mock(ProcessCreatedAuditEventEntity.class); - when(converter.convertToEntity(cloudRuntimeEvent)).thenReturn(entity); + ProcessCreatedAuditEventEntity entity = Mockito.mock(ProcessCreatedAuditEventEntity.class); + Mockito.when(converter.convertToEntity(cloudRuntimeEvent)).thenReturn(entity); CloudRuntimeEvent[] events = { cloudRuntimeEvent }; @@ -75,20 +75,21 @@ public void receiveEventShouldStoreEntity() { ); //then - verify(eventsRepository).saveAll(argumentCaptor.capture()); - assertThat(argumentCaptor.getValue()).containsOnly(entity); + Mockito.verify(eventsRepository).saveAll(argumentCaptor.capture()); + Assertions.assertThat(argumentCaptor.getValue()).containsOnly(entity); } @Test public void messageIdShouldBeSet() { //given - CloudRuntimeEvent cloudRuntimeEvent = mock(CloudRuntimeEventImpl.class); - when(cloudRuntimeEvent.getEventType()).thenReturn(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED); - EventToEntityConverter converter = mock(EventToEntityConverter.class); - when(converters.getConverterByEventTypeName(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name())) + CloudRuntimeEvent cloudRuntimeEvent = Mockito.mock(CloudRuntimeEventImpl.class); + Mockito.when(cloudRuntimeEvent.getEventType()).thenReturn(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED); + EventToEntityConverter converter = Mockito.mock(EventToEntityConverter.class); + Mockito + .when(converters.getConverterByEventTypeName(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name())) .thenReturn(converter); - AuditEventEntity entity = mock(AuditEventEntity.class); - when(converter.convertToEntity(cloudRuntimeEvent)).thenReturn(entity); + AuditEventEntity entity = Mockito.mock(AuditEventEntity.class); + Mockito.when(converter.convertToEntity(cloudRuntimeEvent)).thenReturn(entity); CloudRuntimeEvent[] events = { cloudRuntimeEvent }; @@ -99,6 +100,6 @@ public void messageIdShouldBeSet() { handler.receiveCloudRuntimeEvent(headers, events); //then - verify((CloudRuntimeEventImpl) cloudRuntimeEvent).setMessageId(headers.get("id").toString()); + Mockito.verify((CloudRuntimeEventImpl) cloudRuntimeEvent).setMessageId(headers.get("id").toString()); } } diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 84c391736f8..00000000000 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1,5 +0,0 @@ -org.activiti.cloud.services.audit.jpa.conf.AuditJPAAutoConfiguration -org.activiti.cloud.services.audit.jpa.controllers.config.AuditJPAControllersAutoConfiguration -org.activiti.cloud.services.audit.jpa.repository.config.AuditJPARepositoryAutoConfiguration -org.activiti.cloud.services.audit.jpa.security.config.AuditJPASecurityAutoConfiguration -org.activiti.cloud.services.audit.jpa.streams.config.AuditJPAStreamsAutoConfiguration diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-liquibase/pom.xml b/activiti-cloud-audit-service/activiti-cloud-services-audit-liquibase/pom.xml index 7deeeb000b2..fbcf843b496 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-liquibase/pom.xml +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-liquibase/pom.xml @@ -3,7 +3,7 @@ org.activiti.cloud activiti-cloud-audit-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-audit-dependencies activiti-cloud-services-audit-liquibase diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/pom.xml b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/pom.xml index 072455d76d6..4392f6a8c0b 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/pom.xml +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-audit-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-audit-dependencies @@ -65,6 +65,11 @@ jakarta.persistence jakarta.persistence-api + + org.springframework.boot + spring-boot-autoconfigure + true + org.springframework.data spring-data-jpa diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/converters/APIEventToEntityConverters.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/api/converters/APIEventToEntityConverters.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/converters/APIEventToEntityConverters.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/api/converters/APIEventToEntityConverters.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/converters/EventToEntityConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/api/converters/EventToEntityConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-api/src/main/java/org/activiti/cloud/services/audit/api/converters/EventToEntityConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/api/converters/EventToEntityConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/conf/AuditJPAAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/conf/AuditJPAAutoConfiguration.java similarity index 98% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/conf/AuditJPAAutoConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/conf/AuditJPAAutoConfiguration.java index 8872a80c146..629d4207ce3 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/conf/AuditJPAAutoConfiguration.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/conf/AuditJPAAutoConfiguration.java @@ -18,7 +18,6 @@ import java.util.Set; import org.activiti.cloud.services.audit.api.converters.APIEventToEntityConverters; import org.activiti.cloud.services.audit.api.converters.EventToEntityConverter; -import org.activiti.cloud.services.audit.jpa.assembler.EventRepresentationModelAssembler; import org.activiti.cloud.services.audit.jpa.converters.ActivityCancelledEventConverter; import org.activiti.cloud.services.audit.jpa.converters.ActivityCompletedEventConverter; import org.activiti.cloud.services.audit.jpa.converters.ActivityStartedEventConverter; @@ -75,12 +74,6 @@ @AutoConfiguration public class AuditJPAAutoConfiguration { - @ConditionalOnMissingBean - @Bean - public EventRepresentationModelAssembler eventRepresentationModelAssembler() { - return new EventRepresentationModelAssembler(); - } - @ConditionalOnMissingBean @Bean public EventContextInfoAppender eventContextInfoAppender() { diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCancelledEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCancelledEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCancelledEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCancelledEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCompletedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCompletedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCompletedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityCompletedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityStartedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityStartedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityStartedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ActivityStartedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationDeployedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationDeployedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationDeployedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationDeployedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/BaseEventToEntityConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/BaseEventToEntityConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/BaseEventToEntityConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/BaseEventToEntityConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/EventContextInfoAppender.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/EventContextInfoAppender.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/EventContextInfoAppender.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/EventContextInfoAppender.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageReceivedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageReceivedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageReceivedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageReceivedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSentEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSentEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSentEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSentEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageWaitingEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageWaitingEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageWaitingEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/MessageWaitingEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCancelledEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCancelledEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCancelledEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCancelledEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupAddedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupAddedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupAddedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupAddedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupRemovedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupRemovedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupRemovedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterGroupRemovedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserAddedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserAddedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserAddedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserAddedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserRemovedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserRemovedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserRemovedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserRemovedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCompletedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCompletedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCompletedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCompletedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCreatedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCreatedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCreatedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCreatedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverter.java similarity index 65% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverter.java index f647e2d2146..5211da21f34 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverter.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverter.java @@ -15,22 +15,14 @@ */ package org.activiti.cloud.services.audit.jpa.converters; -import java.util.List; import org.activiti.api.process.model.events.ProcessRuntimeEvent; import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; import org.activiti.cloud.api.model.shared.impl.events.CloudRuntimeEventImpl; import org.activiti.cloud.api.process.model.events.CloudProcessDeletedEvent; import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; -import org.activiti.cloud.services.audit.jpa.events.ProcessAuditEventEntity; import org.activiti.cloud.services.audit.jpa.events.ProcessDeletedAuditEventEntity; -import org.activiti.cloud.services.audit.jpa.repository.EventSpecificationsBuilder; import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; -import org.activiti.cloud.services.audit.jpa.repository.SearchOperation; -import org.activiti.cloud.services.audit.jpa.repository.SpecSearchCriteria; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Order; -import org.springframework.data.jpa.domain.Specification; public class ProcessDeletedEventConverter extends BaseEventToEntityConverter { @@ -57,8 +49,7 @@ public String getSupportedEvent() { @Override protected ProcessDeletedAuditEventEntity createEventEntity(CloudRuntimeEvent cloudRuntimeEvent) { - ProcessAuditEventEntity event = findEvent(cloudRuntimeEvent.getProcessInstanceId()); - return new ProcessDeletedAuditEventEntity(event, (CloudProcessDeletedEvent) cloudRuntimeEvent); + return new ProcessDeletedAuditEventEntity((CloudProcessDeletedEvent) cloudRuntimeEvent); } @Override @@ -71,16 +62,4 @@ protected ProcessDeletedAuditEventEntity createEventEntity(CloudRuntimeEvent clo processDeletedAuditEventEntity.getProcessInstance() ); } - - protected ProcessAuditEventEntity findEvent(String processInstanceId) { - Specification specification = new EventSpecificationsBuilder() - .with(new SpecSearchCriteria(PROCESS_INSTANCE_ID, SearchOperation.EQUALITY, processInstanceId)) - .build(); - List events = eventsRepository.findAll(specification, Sort.by(Order.desc(TIMESTAMP))); - AuditEventEntity lastEvent = events - .stream() - .findFirst() - .orElseThrow(() -> new IllegalStateException(String.format(MISSING_PROCESS_INSTANCE, processInstanceId))); - return ProcessAuditEventEntity.class.cast(lastEvent); - } } diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeployedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeployedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeployedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeployedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessResumedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessResumedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessResumedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessResumedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessSuspendedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessSuspendedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessSuspendedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessSuspendedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessUpdatedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessUpdatedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessUpdatedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/ProcessUpdatedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SequenceFlowTakenEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SequenceFlowTakenEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SequenceFlowTakenEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SequenceFlowTakenEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskAssignedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskAssignedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskAssignedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskAssignedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCancelledEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCancelledEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCancelledEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCancelledEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupAddedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupAddedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupAddedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupAddedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupRemovedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupRemovedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupRemovedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateGroupRemovedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserRemovedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserRemovedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserRemovedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserRemovedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCompletedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCompletedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCompletedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCompletedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskSuspendedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskSuspendedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskSuspendedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskSuspendedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskUpdatedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskUpdatedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskUpdatedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TaskUpdatedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerCancelledEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerCancelledEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerCancelledEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerCancelledEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerExecutedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerExecutedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerExecutedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerExecutedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFailedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFailedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFailedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFailedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFiredEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFiredEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFiredEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerFiredEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerRetriesDecrementedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerRetriesDecrementedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerRetriesDecrementedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerRetriesDecrementedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerScheduledEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerScheduledEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerScheduledEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/TimerScheduledEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableCreatedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableCreatedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableCreatedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableCreatedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableDeletedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableDeletedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableDeletedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableDeletedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableUpdatedEventConverter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableUpdatedEventConverter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableUpdatedEventConverter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/converters/VariableUpdatedEventConverter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/MessageSubscriptionCancelledAuditEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/MessageSubscriptionCancelledAuditEventEntity.java index 6de618deedc..ddb451fa75c 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/MessageSubscriptionCancelledAuditEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/MessageSubscriptionCancelledAuditEventEntity.java @@ -22,7 +22,6 @@ import org.activiti.api.process.model.MessageSubscription; import org.activiti.cloud.api.process.model.events.CloudMessageSubscriptionCancelledEvent; import org.activiti.cloud.services.audit.jpa.converters.json.MessageSubscriptionJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity @DiscriminatorValue(value = MessageSubscriptionCancelledAuditEventEntity.MESSAGE_SUBSCRIPTION_CANCELLED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterGroupAddedEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterGroupAddedEventEntity.java index f36b74afc9d..3986002c57c 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterGroupAddedEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterGroupAddedEventEntity.java @@ -23,7 +23,6 @@ import org.activiti.api.runtime.model.impl.ProcessCandidateStarterGroupImpl; import org.activiti.cloud.api.process.model.events.CloudProcessCandidateStarterGroupAddedEvent; import org.activiti.cloud.services.audit.jpa.converters.json.ProcessCandidateStarterGroupJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = ProcessCandidateStarterGroupAddedEventEntity.PROCESS_CANDIDATE_STARTER_GROUP_ADDED_EVENT) @DiscriminatorValue(value = ProcessCandidateStarterGroupAddedEventEntity.PROCESS_CANDIDATE_STARTER_GROUP_ADDED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserAddedEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserAddedEventEntity.java index 297afdea1b4..4cf9f9f4c50 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserAddedEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserAddedEventEntity.java @@ -23,7 +23,6 @@ import org.activiti.api.runtime.model.impl.ProcessCandidateStarterUserImpl; import org.activiti.cloud.api.process.model.events.CloudProcessCandidateStarterUserAddedEvent; import org.activiti.cloud.services.audit.jpa.converters.json.ProcessCandidateStarterUserJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = ProcessCandidateStarterUserAddedEventEntity.PROCESS_CANDIDATE_STARTER_USER_ADDED_EVENT) @DiscriminatorValue(value = ProcessCandidateStarterUserAddedEventEntity.PROCESS_CANDIDATE_STARTER_USER_ADDED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserRemovedEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserRemovedEventEntity.java index 1d5c4c5a446..7558dc9c7fb 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserRemovedEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessCandidateStarterUserRemovedEventEntity.java @@ -23,7 +23,6 @@ import org.activiti.api.runtime.model.impl.ProcessCandidateStarterUserImpl; import org.activiti.cloud.api.process.model.events.CloudProcessCandidateStarterUserRemovedEvent; import org.activiti.cloud.services.audit.jpa.converters.json.ProcessCandidateStarterUserJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = ProcessCandidateStarterUserRemovedEventEntity.PROCESS_CANDIDATE_STARTER_USER_REMOVED_EVENT) @DiscriminatorValue(value = ProcessCandidateStarterUserRemovedEventEntity.PROCESS_CANDIDATE_STARTER_USER_REMOVED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessDeployedAuditEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessDeployedAuditEventEntity.java index b4dbdf4f479..f14cfe91cee 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessDeployedAuditEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/ProcessDeployedAuditEventEntity.java @@ -22,7 +22,6 @@ import org.activiti.api.process.model.ProcessDefinition; import org.activiti.cloud.api.process.model.events.CloudProcessDeployedEvent; import org.activiti.cloud.services.audit.jpa.converters.json.ProcessDefinitionJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = ProcessDeployedAuditEventEntity.PROCESS_DEPLOYED_EVENT) @DiscriminatorValue(value = ProcessDeployedAuditEventEntity.PROCESS_DEPLOYED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/SequenceFlowAuditEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/SequenceFlowAuditEventEntity.java index 1488c8ba60e..ef865a756ba 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/SequenceFlowAuditEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/SequenceFlowAuditEventEntity.java @@ -22,7 +22,6 @@ import org.activiti.api.process.model.BPMNSequenceFlow; import org.activiti.cloud.api.process.model.events.CloudSequenceFlowTakenEvent; import org.activiti.cloud.services.audit.jpa.converters.json.SequenceFlowJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = SequenceFlowAuditEventEntity.SEQUENCE_FLOW_TAKEN_EVENT) @DiscriminatorValue(value = SequenceFlowAuditEventEntity.SEQUENCE_FLOW_TAKEN_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupAddedEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupAddedEventEntity.java index 9a7a8f12b18..876c7221992 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupAddedEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupAddedEventEntity.java @@ -23,7 +23,6 @@ import org.activiti.api.task.model.impl.TaskCandidateGroupImpl; import org.activiti.cloud.api.task.model.events.CloudTaskCandidateGroupAddedEvent; import org.activiti.cloud.services.audit.jpa.converters.json.TaskCandidateGroupJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = TaskCandidateGroupAddedEventEntity.TASK_CANDIDATE_GROUP_ADDED_EVENT) @DiscriminatorValue(value = TaskCandidateGroupAddedEventEntity.TASK_CANDIDATE_GROUP_ADDED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupRemovedEventEntity.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupRemovedEventEntity.java index acce3161782..cb4ad221dba 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupRemovedEventEntity.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/events/TaskCandidateGroupRemovedEventEntity.java @@ -23,7 +23,6 @@ import org.activiti.api.task.model.impl.TaskCandidateGroupImpl; import org.activiti.cloud.api.task.model.events.CloudTaskCandidateGroupRemovedEvent; import org.activiti.cloud.services.audit.jpa.converters.json.TaskCandidateGroupJpaJsonConverter; -import org.hibernate.annotations.DynamicInsert; @Entity(name = TaskCandidateGroupRemovedEventEntity.TASK_CANDIDATE_GROUP_REMOVED_EVENT) @DiscriminatorValue(value = TaskCandidateGroupRemovedEventEntity.TASK_CANDIDATE_GROUP_REMOVED_EVENT) diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecification.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecification.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecification.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecification.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecificationsBuilder.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecificationsBuilder.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecificationsBuilder.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventSpecificationsBuilder.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventsRepository.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventsRepository.java similarity index 91% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventsRepository.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventsRepository.java index 5567b8f4c1f..cc5b08c6ddd 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventsRepository.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/EventsRepository.java @@ -21,12 +21,12 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface EventsRepository extends PagingAndSortingRepository, JpaSpecificationExecutor, CrudRepository { Optional findByEventId(String eventId); Collection findAllByOrderByTimestampDesc(); + + Collection findAllByTimestampBetweenOrderByTimestampDesc(Long startDateTime, Long endDateTime); } diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchCriteria.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchCriteria.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchCriteria.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchCriteria.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchOperation.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchOperation.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchOperation.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SearchOperation.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SpecSearchCriteria.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SpecSearchCriteria.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SpecSearchCriteria.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/SpecSearchCriteria.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/config/AuditJPARepositoryAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/config/AuditJPARepositoryAutoConfiguration.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/repository/config/AuditJPARepositoryAutoConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/java/org/activiti/cloud/services/audit/jpa/repository/config/AuditJPARepositoryAutoConfiguration.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..e966478ba3a --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +org.activiti.cloud.services.audit.jpa.conf.AuditJPAAutoConfiguration +org.activiti.cloud.services.audit.jpa.repository.config.AuditJPARepositoryAutoConfiguration diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ApplicationRollbackEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ErrorReceivedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationErrorReceivedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationRequestedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/IntegrationResultReceivedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/MessageSubscriptionCancelledEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessCandidateStarterUserEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverterTest.java similarity index 88% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverterTest.java index 30134b72454..510e4a45af4 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverterTest.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessDeletedEventConverterTest.java @@ -16,8 +16,6 @@ package org.activiti.cloud.services.audit.jpa.converters; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; import java.util.Arrays; import java.util.List; @@ -28,7 +26,6 @@ import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; import org.activiti.cloud.api.model.shared.impl.events.CloudRuntimeEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; -import org.activiti.cloud.services.audit.api.converters.CloudRuntimeEventType; import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; import org.activiti.cloud.services.audit.jpa.events.ProcessCompletedEventEntity; import org.activiti.cloud.services.audit.jpa.events.ProcessDeletedAuditEventEntity; @@ -38,7 +35,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.Sort; @ExtendWith(MockitoExtension.class) public class ProcessDeletedEventConverterTest { @@ -66,10 +62,8 @@ public void createEventEntityShouldReturnEntity() { //given String processDefinitionId = UUID.randomUUID().toString(); String processInstanceId = UUID.randomUUID().toString(); - given(eventsRepository.findAll(any(), any(Sort.class))) - .willReturn(buildCompletedEntities(processDefinitionId, processInstanceId)); - CloudRuntimeEvent runtimeEvent = buildEvent(processInstanceId); + CloudRuntimeEvent runtimeEvent = buildEvent(processInstanceId, processDefinitionId); //when ProcessDeletedAuditEventEntity event = converter.createEventEntity(runtimeEvent); @@ -84,10 +78,8 @@ public void createAPIEventShouldReturnEvent() { //given String processDefinitionId = UUID.randomUUID().toString(); String processInstanceId = UUID.randomUUID().toString(); - given(eventsRepository.findAll(any(), any(Sort.class))) - .willReturn(buildCompletedEntities(processDefinitionId, processInstanceId)); - CloudRuntimeEvent runtimeEvent = buildEvent(processInstanceId); + CloudRuntimeEvent runtimeEvent = buildEvent(processInstanceId, processDefinitionId); //when ProcessDeletedAuditEventEntity event = converter.createEventEntity(runtimeEvent); @@ -98,9 +90,10 @@ public void createAPIEventShouldReturnEvent() { assertThat(apiEvent.getProcessInstanceId()).isEqualTo(processInstanceId); } - private CloudRuntimeEvent buildEvent(String processInstanceId) { + private CloudRuntimeEvent buildEvent(String processInstanceId, String processDefinitionId) { ProcessInstanceImpl instance = new ProcessInstanceImpl(); instance.setId(processInstanceId); + instance.setProcessDefinitionId(processDefinitionId); CloudProcessDeletedEventImpl event = new CloudProcessDeletedEventImpl(instance); event.setProcessInstanceId(processInstanceId); @@ -121,7 +114,7 @@ private List buildCompletedEntities( ) { ProcessCompletedEventEntity event = new ProcessCompletedEventEntity(); event.setProcessDefinitionId(processDefinitionId); - event.setEventType(CloudRuntimeEventType.PROCESS_COMPLETED.name()); + event.setEventType("PROCESS_COMPLETED"); event.setProcessInstanceId(processInstanceId); event.setProcessInstance(buildProcessInstance(processInstanceId, processDefinitionId)); return Arrays.asList(event); diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/ProcessStartedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/SignalReceivedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCandidateUserAddedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TaskCreatedEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TimerEventConverterTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TimerEventConverterTest.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TimerEventConverterTest.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-model/src/test/java/org/activiti/cloud/services/audit/jpa/converters/TimerEventConverterTest.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/pom.xml b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/pom.xml similarity index 90% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/pom.xml rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/pom.xml index 3966a0333d3..fdb4bd5a782 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/pom.xml +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/pom.xml @@ -5,10 +5,10 @@ org.activiti.cloud activiti-cloud-audit-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-audit-dependencies - activiti-cloud-services-audit-jpa + activiti-cloud-services-audit-rest Activiti Cloud Audit :: Services :: Audit JPA 5.6 @@ -22,10 +22,6 @@ org.activiti.cloud activiti-cloud-service-common-config - - org.activiti.cloud - activiti-cloud-service-messaging-config - org.activiti.cloud activiti-cloud-services-audit-api @@ -91,10 +87,6 @@ org.hibernate.orm hibernate-core - - org.springframework.cloud - spring-cloud-stream - com.fasterxml.jackson.core jackson-annotations @@ -132,11 +124,6 @@ jakarta.persistence jakarta.persistence-api - - org.springframework.cloud - spring-cloud-starter-stream-rabbit - test - org.springframework.boot spring-boot-starter-data-jpa diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/EventRepresentationModelAssembler.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/EventRepresentationModelAssembler.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/EventRepresentationModelAssembler.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/EventRepresentationModelAssembler.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/config/EventRepresentationModelAssemblerConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/config/EventRepresentationModelAssemblerConfiguration.java new file mode 100644 index 00000000000..cf42a79e220 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/assembler/config/EventRepresentationModelAssemblerConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.audit.jpa.assembler.config; + +import org.activiti.cloud.services.audit.jpa.assembler.EventRepresentationModelAssembler; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class EventRepresentationModelAssemblerConfiguration { + + @ConditionalOnMissingBean + @Bean + public EventRepresentationModelAssembler eventRepresentationModelAssembler() { + return new EventRepresentationModelAssembler(); + } +} diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsAdminControllerImpl.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsAdminControllerImpl.java similarity index 83% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsAdminControllerImpl.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsAdminControllerImpl.java index 5966d613c3a..9f1568c1f88 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsAdminControllerImpl.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsAdminControllerImpl.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletResponse; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -29,10 +30,12 @@ import org.activiti.cloud.services.audit.jpa.assembler.EventRepresentationModelAssembler; import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; +import org.activiti.cloud.services.audit.jpa.service.AuditEventsAdminService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.PagedModel; @@ -41,6 +44,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -60,19 +64,23 @@ public class AuditEventsAdminControllerImpl implements AuditEventsAdminControlle private final AuditEventsExporter auditEventsExporter; + private final AuditEventsAdminService auditEventsAdminService; + @Autowired public AuditEventsAdminControllerImpl( EventsRepository eventsRepository, EventRepresentationModelAssembler eventRepresentationModelAssembler, APIEventToEntityConverters eventConverters, AlfrescoPagedModelAssembler> pagedCollectionModelAssembler, - ObjectMapper objectMapper + ObjectMapper objectMapper, + AuditEventsAdminService auditEventsAdminService ) { this.eventsRepository = eventsRepository; this.eventRepresentationModelAssembler = eventRepresentationModelAssembler; this.eventConverters = eventConverters; this.pagedCollectionModelAssembler = pagedCollectionModelAssembler; this.auditEventsExporter = new AuditEventsExporter(objectMapper); + this.auditEventsAdminService = auditEventsAdminService; } @RequestMapping(method = RequestMethod.GET) @@ -89,11 +97,15 @@ public PagedModel>> find } @GetMapping(path = "/export/{fileName}") - public void export(@PathVariable(value = "fileName") String fileName, HttpServletResponse response) - throws Exception { - Collection allAuditInPage = eventsRepository.findAllByOrderByTimestampDesc(); - - List> events = toCloudRuntimeEvents(allAuditInPage); + public void export( + @PathVariable(value = "fileName") String fileName, + @RequestParam(value = "from", required = true) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from, + @RequestParam(value = "to", required = true) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to, + HttpServletResponse response + ) throws Exception { + Collection audits = auditEventsAdminService.findAuditsBetweenDates(from, to); + + List> events = toCloudRuntimeEvents(audits); auditEventsExporter.exportCsv(events, fileName, response); } diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsControllerImpl.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsControllerImpl.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsControllerImpl.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsControllerImpl.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsDeleteController.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsDeleteController.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsDeleteController.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsDeleteController.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsExporter.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsExporter.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsExporter.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/AuditEventsExporter.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/config/AuditJPAControllersAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/config/AuditJPAControllersAutoConfiguration.java new file mode 100644 index 00000000000..2cd6b8c183c --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/config/AuditJPAControllersAutoConfiguration.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.audit.jpa.controllers.config; + +import org.activiti.cloud.services.audit.jpa.assembler.config.EventRepresentationModelAssemblerConfiguration; +import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsAdminControllerImpl; +import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsControllerImpl; +import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsDeleteController; +import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; +import org.activiti.cloud.services.audit.jpa.service.AuditEventsAdminService; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.data.rest.core.config.RepositoryRestConfiguration; +import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer; +import org.springframework.web.servlet.config.annotation.CorsRegistry; + +@AutoConfiguration +@Import( + { + EventRepresentationModelAssemblerConfiguration.class, + AuditEventsAdminControllerImpl.class, + AuditEventsControllerImpl.class, + AuditEventsDeleteController.class, + } +) +public class AuditJPAControllersAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + RepositoryRestConfigurer dataRestRepositoryRestConfigurer() { + return new RepositoryRestConfigurer() { + @Override + public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) { + config.disableDefaultExposure(); + } + }; + } + + @Bean + public AuditEventsAdminService auditEventsAdminService(EventsRepository eventsRepository) { + return new AuditEventsAdminService(eventsRepository); + } +} diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/CsvLogEntry.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/CsvLogEntry.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/CsvLogEntry.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/CsvLogEntry.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonConvertor.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonConvertor.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonConvertor.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonConvertor.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonStrategy.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonStrategy.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonStrategy.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/controllers/csv/ObjectToJsonStrategy.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/AlwaysTrueSpecification.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/AlwaysTrueSpecification.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/AlwaysTrueSpecification.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/AlwaysTrueSpecification.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationProcessDefSecuritySpecification.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationProcessDefSecuritySpecification.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationProcessDefSecuritySpecification.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationProcessDefSecuritySpecification.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationSecuritySpecification.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationSecuritySpecification.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationSecuritySpecification.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/ApplicationSecuritySpecification.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/ImpossibleSpecification.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/ImpossibleSpecification.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/ImpossibleSpecification.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/ImpossibleSpecification.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/SecurityPoliciesApplicationServiceImpl.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/SecurityPoliciesApplicationServiceImpl.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/SecurityPoliciesApplicationServiceImpl.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/SecurityPoliciesApplicationServiceImpl.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/config/AuditJPASecurityAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/config/AuditJPASecurityAutoConfiguration.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/java/org/activiti/cloud/services/audit/jpa/security/config/AuditJPASecurityAutoConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/security/config/AuditJPASecurityAutoConfiguration.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/service/AuditEventsAdminService.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/service/AuditEventsAdminService.java new file mode 100644 index 00000000000..31516e4c606 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/java/org/activiti/cloud/services/audit/jpa/service/AuditEventsAdminService.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.audit.jpa.service; + +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.Collection; +import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; +import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; + +public class AuditEventsAdminService { + + private final EventsRepository eventsRepository; + + public AuditEventsAdminService(EventsRepository eventsRepository) { + this.eventsRepository = eventsRepository; + } + + public Collection findAuditsBetweenDates(LocalDate fromDate, LocalDate toDate) { + if (fromDate.isAfter(toDate)) { + throw new IllegalArgumentException("From date cannot be after to date"); + } + + long daysBetween = ChronoUnit.DAYS.between(fromDate, toDate); + + if (daysBetween > 31) { + throw new IllegalArgumentException("Difference between dates cannot be more than 31 days"); + } + + Long startDateTime = fromDate.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(); + Long endDateTime = toDate.atStartOfDay().plusDays(1).toInstant(ZoneOffset.UTC).toEpochMilli(); + + return eventsRepository.findAllByTimestampBetweenOrderByTimestampDesc(startDateTime, endDateTime); + } +} diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/resources/META-INF/application.properties b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/resources/META-INF/application.properties similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/main/resources/META-INF/application.properties rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/resources/META-INF/application.properties diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..acd407736e0 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +org.activiti.cloud.services.audit.jpa.controllers.config.AuditJPAControllersAutoConfiguration +org.activiti.cloud.services.audit.jpa.security.config.AuditJPASecurityAutoConfiguration diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/Application.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/Application.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/Application.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/Application.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventDeleteControllerIT.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventDeleteControllerIT.java similarity index 94% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventDeleteControllerIT.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventDeleteControllerIT.java index 7fd6ee325aa..36843ee78bd 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventDeleteControllerIT.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventDeleteControllerIT.java @@ -31,6 +31,7 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.services.audit.api.config.AuditAPIAutoConfiguration; import org.activiti.cloud.services.audit.api.resources.EventsLinkRelationProvider; +import org.activiti.cloud.services.audit.jpa.assembler.config.EventRepresentationModelAssemblerConfiguration; import org.activiti.cloud.services.audit.jpa.conf.AuditJPAAutoConfiguration; import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsDeleteController; import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; @@ -52,7 +53,14 @@ @WebMvcTest(AuditEventsDeleteController.class) @EnableSpringDataWebSupport @AutoConfigureMockMvc -@Import({ AuditAPIAutoConfiguration.class, AuditJPAAutoConfiguration.class, AlfrescoWebAutoConfiguration.class }) +@Import( + { + EventRepresentationModelAssemblerConfiguration.class, + AuditAPIAutoConfiguration.class, + AuditJPAAutoConfiguration.class, + AlfrescoWebAutoConfiguration.class, + } +) public class AuditEventDeleteControllerIT { private static final String DOCUMENTATION_ALFRESCO_IDENTIFIER = "events-alfresco"; diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventsControllerImplIT.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventsControllerImplIT.java similarity index 98% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventsControllerImplIT.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventsControllerImplIT.java index 22c3ebb2fd7..972b8c452de 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventsControllerImplIT.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/AuditEventsControllerImplIT.java @@ -45,6 +45,7 @@ import org.activiti.cloud.alfresco.argument.resolver.AlfrescoPageRequest; import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.services.audit.api.config.AuditAPIAutoConfiguration; +import org.activiti.cloud.services.audit.jpa.assembler.config.EventRepresentationModelAssemblerConfiguration; import org.activiti.cloud.services.audit.jpa.conf.AuditJPAAutoConfiguration; import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsControllerImpl; import org.activiti.cloud.services.audit.jpa.events.ActivityStartedAuditEventEntity; @@ -79,6 +80,7 @@ @AutoConfigureMockMvc @Import( { + EventRepresentationModelAssemblerConfiguration.class, AuditAPIAutoConfiguration.class, AuditJPAAutoConfiguration.class, AuditJPASecurityAutoConfiguration.class, diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/EventsEngineEventsAdminControllerIT.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/EventsEngineEventsAdminControllerIT.java similarity index 90% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/EventsEngineEventsAdminControllerIT.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/EventsEngineEventsAdminControllerIT.java index 847f83a79ff..7bbf58acedf 100644 --- a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/controller/EventsEngineEventsAdminControllerIT.java +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/controller/EventsEngineEventsAdminControllerIT.java @@ -18,6 +18,7 @@ import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.when; import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION; @@ -36,12 +37,16 @@ import org.activiti.cloud.alfresco.argument.resolver.AlfrescoPageRequest; import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.services.audit.api.config.AuditAPIAutoConfiguration; +import org.activiti.cloud.services.audit.jpa.assembler.config.EventRepresentationModelAssemblerConfiguration; import org.activiti.cloud.services.audit.jpa.conf.AuditJPAAutoConfiguration; import org.activiti.cloud.services.audit.jpa.controllers.AuditEventsAdminControllerImpl; +import org.activiti.cloud.services.audit.jpa.controllers.config.AuditJPAControllersAutoConfiguration; import org.activiti.cloud.services.audit.jpa.events.AuditEventEntity; import org.activiti.cloud.services.audit.jpa.events.ProcessStartedAuditEventEntity; import org.activiti.cloud.services.audit.jpa.events.VariableCreatedEventEntity; import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; +import org.activiti.cloud.services.audit.jpa.security.config.AuditJPASecurityAutoConfiguration; +import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -61,7 +66,16 @@ @WebMvcTest(AuditEventsAdminControllerImpl.class) @EnableSpringDataWebSupport @AutoConfigureMockMvc -@Import({ AuditAPIAutoConfiguration.class, AuditJPAAutoConfiguration.class, AlfrescoWebAutoConfiguration.class }) +@Import( + { + EventRepresentationModelAssemblerConfiguration.class, + AuditAPIAutoConfiguration.class, + AuditJPAAutoConfiguration.class, + AlfrescoWebAutoConfiguration.class, + AuditJPAControllersAutoConfiguration.class, + AuditJPASecurityAutoConfiguration.class, + } +) class EventsEngineEventsAdminControllerIT { private static final String HEADER_ATTACHMENT_FILENAME = "attachment;filename="; @@ -86,6 +100,9 @@ class EventsEngineEventsAdminControllerIT { @MockBean private UserGroupManager userGroupManager; + @MockBean + private SecurityPoliciesProperties securityPoliciesProperties; + @BeforeEach void setUp() throws Exception { when(securityManager.getAuthenticatedUserId()).thenReturn("user"); @@ -108,10 +125,14 @@ void exportEvents() throws Exception { List events = buildEventsData(1); events.add(buildVariableAuditEventEntity(2)); - given(eventsRepository.findAllByOrderByTimestampDesc()).willReturn(events); + given(eventsRepository.findAllByTimestampBetweenOrderByTimestampDesc(anyLong(), anyLong())).willReturn(events); MvcResult response = mockMvc - .perform(get("/admin/{version}/events/export/" + CSV_FILENAME, "v1")) + .perform( + get("/admin/{version}/events/export/" + CSV_FILENAME, "v1") + .param("from", "2024-07-22") + .param("to", "2024-07-24") + ) .andExpect(status().isOk()) .andReturn(); diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/security/RestrictEventQueryIT.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/security/RestrictEventQueryIT.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/java/org/activiti/cloud/services/audit/jpa/security/RestrictEventQueryIT.java rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/security/RestrictEventQueryIT.java diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/service/AuditEventsAdminServiceTest.java b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/service/AuditEventsAdminServiceTest.java new file mode 100644 index 00000000000..8560f6f59fd --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/java/org/activiti/cloud/services/audit/jpa/service/AuditEventsAdminServiceTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.audit.jpa.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.verify; + +import java.time.LocalDate; +import org.activiti.cloud.services.audit.jpa.repository.EventsRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class AuditEventsAdminServiceTest { + + @Mock + private EventsRepository eventsRepository; + + @InjectMocks + private AuditEventsAdminService auditEventsAdminService; + + @Test + void should_throw_exception_when_from_date_is_after_to_date() { + // given + LocalDate fromDate = LocalDate.of(2020, 1, 1); + LocalDate toDate = LocalDate.of(2019, 1, 1); + + // when + IllegalArgumentException thrown = assertThrows( + IllegalArgumentException.class, + () -> auditEventsAdminService.findAuditsBetweenDates(fromDate, toDate) + ); + + // then + assertEquals("From date cannot be after to date", thrown.getMessage()); + } + + @Test + void should_throw_exception_when_difference_between_dates_is_more_than_31_days() { + // given + LocalDate fromDate = LocalDate.of(2020, 1, 1); + LocalDate toDate = LocalDate.of(2020, 3, 1); + + // when + IllegalArgumentException thrown = assertThrows( + IllegalArgumentException.class, + () -> auditEventsAdminService.findAuditsBetweenDates(fromDate, toDate) + ); + + // then + assertEquals("Difference between dates cannot be more than 31 days", thrown.getMessage()); + } + + @Test + void should_return_events_between_dates() { + // given + LocalDate fromDate = LocalDate.of(2020, 1, 1); + LocalDate toDate = LocalDate.of(2020, 1, 2); + + // when + auditEventsAdminService.findAuditsBetweenDates(fromDate, toDate); + + // then + verify(eventsRepository).findAllByTimestampBetweenOrderByTimestampDesc(anyLong(), anyLong()); + } +} diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/resources/application-test.properties b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/resources/application-test.properties similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/resources/application-test.properties rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/resources/application-test.properties diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/resources/application.properties b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/resources/application.properties similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/resources/application.properties rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/resources/application.properties diff --git a/activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/resources/logback-test.xml b/activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/resources/logback-test.xml similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-services-audit-jpa/src/test/resources/logback-test.xml rename to activiti-cloud-audit-service/activiti-cloud-services-audit-rest/src/test/resources/logback-test.xml diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/pom.xml b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/pom.xml new file mode 100644 index 00000000000..e7a343bec8d --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/pom.xml @@ -0,0 +1,120 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-audit-dependencies + 8.7.0-SNAPSHOT + ../activiti-cloud-audit-dependencies + + + activiti-cloud-starter-audit-consumer + Activiti Cloud Starter :: Audit Events Consumer + + + + org.springframework.boot + spring-boot-starter + + + org.activiti.cloud + activiti-cloud-services-audit-consumer + + + org.activiti.cloud + activiti-cloud-services-audit-liquibase + + + org.activiti.cloud + activiti-cloud-services-metadata + + + org.activiti.cloud + activiti-cloud-service-messaging-config + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.activiti.cloud + activiti-cloud-services-monitoring + + + org.activiti.cloud + activiti-cloud-services-logging + + + org.springframework.data + spring-data-commons + + + org.slf4j + slf4j-api + + + com.querydsl + querydsl-core + + + org.springframework.cloud + spring-cloud-commons + + + org.awaitility + awaitility + test + + + com.h2database + h2 + test + + + ch.qos.logback + logback-classic + test + + + org.springframework.cloud + spring-cloud-stream-test-binder + test + + + org.activiti.cloud + activiti-cloud-services-test-containers + test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + test + + + org.testcontainers + rabbitmq + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + + + diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/java/org/activiti/cloud/starter/audit/consumer/config/ActivitiAuditConsumerAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/java/org/activiti/cloud/starter/audit/consumer/config/ActivitiAuditConsumerAutoConfiguration.java new file mode 100644 index 00000000000..af789fc520b --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/java/org/activiti/cloud/starter/audit/consumer/config/ActivitiAuditConsumerAutoConfiguration.java @@ -0,0 +1,23 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.starter.audit.consumer.config; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.PropertySource; + +@AutoConfiguration +@PropertySource("classpath:audit-messaging.properties") +public class ActivitiAuditConsumerAutoConfiguration {} diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..cde795b076c --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.activiti.cloud.starter.audit.consumer.config.ActivitiAuditConsumerAutoConfiguration diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/resources/audit-messaging.properties b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/audit-messaging.properties similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/resources/audit-messaging.properties rename to activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/audit-messaging.properties diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/resources/metadata.properties b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/metadata.properties similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/resources/metadata.properties rename to activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/main/resources/metadata.properties diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/test/java/org/activiti/cloud/starter/audit/consumer/test/ActivitiAuditConsumerAutoConfigurationTest.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/test/java/org/activiti/cloud/starter/audit/consumer/test/ActivitiAuditConsumerAutoConfigurationTest.java new file mode 100644 index 00000000000..c1992e6fd31 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/test/java/org/activiti/cloud/starter/audit/consumer/test/ActivitiAuditConsumerAutoConfigurationTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.starter.audit.consumer.test; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.stream.binder.test.EnableTestBinder; + +@SpringBootTest +@SpringBootApplication +@EnableTestBinder +public class ActivitiAuditConsumerAutoConfigurationTest { + + @Test + void contextLoads() {} +} diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/test/resources/logback-test.xml b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e1f95399f50 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-consumer/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/pom.xml b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/pom.xml new file mode 100644 index 00000000000..cdb5fa2c37a --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/pom.xml @@ -0,0 +1,205 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-audit-dependencies + 8.7.0-SNAPSHOT + ../activiti-cloud-audit-dependencies + + + activiti-cloud-starter-audit-rest + Activiti Cloud Starter :: Audit Rest Api + + + + org.activiti.cloud + activiti-cloud-services-common-identity-keycloak + + + org.activiti.cloud + activiti-cloud-services-common-security-keycloak + + + org.activiti.cloud + activiti-cloud-services-audit-rest + + + org.activiti.cloud + activiti-cloud-services-audit-liquibase + + + org.activiti.cloud + activiti-cloud-services-metadata + + + org.activiti.cloud + activiti-cloud-services-swagger + + + org.activiti.cloud + activiti-cloud-service-error-handlers + + + com.fasterxml.jackson.core + jackson-annotations + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-hateoas + + + org.springframework.hateoas + spring-hateoas + + + org.springframework + spring-context + + + org.springframework + spring-beans + + + org.springframework + spring-web + + + org.activiti.cloud + activiti-cloud-services-monitoring + + + org.activiti.cloud + activiti-cloud-services-logging + + + org.springframework.data + spring-data-commons + + + org.slf4j + slf4j-api + + + com.querydsl + querydsl-core + + + org.springframework + spring-core + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.data + spring-data-jpa + + + org.springframework.boot + spring-boot + + + org.awaitility + awaitility + test + + + com.h2database + h2 + test + + + ch.qos.logback + logback-classic + test + + + org.activiti.cloud + activiti-cloud-services-test + test + + + org.activiti.cloud + activiti-cloud-services-test-containers + test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + test + + + org.testcontainers + rabbitmq + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + + org.assertj + assertj-assertions-generator-maven-plugin + + + + generate-assertions + + + + + + org.activiti.cloud.services.core.model + org.activiti.cloud.services.audit.events + + + org.springframework.http.ResponseEntity + + + true + + ${generated-assertions-package} + + org\.activiti\.services\.core\.model\.converter.* + org\.activiti\.services\.core\.model\.commands.* + + ${generated-assertions-folder} + true + false + false + false + + + + + + diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/ActivitiAuditAutoConfiguration.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/ActivitiAuditAutoConfiguration.java similarity index 88% rename from activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/ActivitiAuditAutoConfiguration.java rename to activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/ActivitiAuditAutoConfiguration.java index f11490de8cb..1160eeb77d3 100644 --- a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/ActivitiAuditAutoConfiguration.java +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/ActivitiAuditAutoConfiguration.java @@ -17,9 +17,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.PropertySource; @AutoConfiguration @Import(AuditSwaggerConfig.class) -@PropertySource("classpath:audit-messaging.properties") public class ActivitiAuditAutoConfiguration {} diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/AuditSwaggerConfig.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/AuditSwaggerConfig.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/AuditSwaggerConfig.java rename to activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/AuditSwaggerConfig.java diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/EnableActivitiAudit.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/EnableActivitiAudit.java similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/java/org/activiti/cloud/starter/audit/configuration/EnableActivitiAudit.java rename to activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/java/org/activiti/cloud/starter/audit/configuration/EnableActivitiAudit.java diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports similarity index 100% rename from activiti-cloud-audit-service/activiti-cloud-starter-audit/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename to activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/test/java/org/activiti/cloud/starter/audit/test/ActivitiCloudStarterAuditRestTest.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/test/java/org/activiti/cloud/starter/audit/test/ActivitiCloudStarterAuditRestTest.java new file mode 100644 index 00000000000..b7fddea4f12 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/test/java/org/activiti/cloud/starter/audit/test/ActivitiCloudStarterAuditRestTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.starter.audit.test; + +import org.activiti.cloud.starter.audit.configuration.EnableActivitiAudit; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@SpringBootApplication +@EnableActivitiAudit +public class ActivitiCloudStarterAuditRestTest { + + @Test + void contextLoads() {} +} diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/test/resources/logback-test.xml b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e1f95399f50 --- /dev/null +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit-rest/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/pom.xml b/activiti-cloud-audit-service/activiti-cloud-starter-audit/pom.xml index 625d68e0b6f..c0f2af2ceb6 100644 --- a/activiti-cloud-audit-service/activiti-cloud-starter-audit/pom.xml +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit/pom.xml @@ -6,11 +6,11 @@ org.activiti.cloud activiti-cloud-audit-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-audit-dependencies activiti-cloud-starter-audit - Activiti Cloud Starter :: Audit + Activiti Cloud Starter :: All In One org.activiti.cloud @@ -22,19 +22,19 @@ org.activiti.cloud - activiti-cloud-services-audit-jpa + activiti-cloud-starter-audit-rest org.activiti.cloud - activiti-cloud-services-audit-liquibase + activiti-cloud-starter-audit-consumer org.activiti.cloud - activiti-cloud-services-metadata + activiti-cloud-services-audit-liquibase org.activiti.cloud - activiti-cloud-service-messaging-config + activiti-cloud-services-metadata org.activiti.cloud @@ -100,10 +100,6 @@ com.querydsl querydsl-core - - org.springframework.cloud - spring-cloud-commons - org.springframework spring-core diff --git a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/test/java/org/activiti/cloud/starter/audit/tests/it/AuditServiceIT.java b/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/test/java/org/activiti/cloud/starter/audit/tests/it/AuditServiceIT.java index 3236e6b2ec1..5c7c71a70b0 100644 --- a/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/test/java/org/activiti/cloud/starter/audit/tests/it/AuditServiceIT.java +++ b/activiti-cloud-audit-service/activiti-cloud-starter-audit/src/test/java/org/activiti/cloud/starter/audit/tests/it/AuditServiceIT.java @@ -85,6 +85,7 @@ import org.activiti.cloud.api.process.model.impl.events.CloudProcessCandidateStarterUserAddedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessCandidateStarterUserRemovedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessCompletedEventImpl; +import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeployedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessStartedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessSuspendedEventImpl; @@ -142,6 +143,7 @@ public void cleanUp() { public void findAllShouldReturnAllAvailableEvents() { //given List coveredEvents = getTestEvents(); + producer.send(coveredEvents.toArray(new CloudRuntimeEvent[coveredEvents.size()])); await() @@ -1130,6 +1132,14 @@ private List getTestEvents() { ) ); + testEvents.add( + new CloudProcessDeletedEventImpl( + "ProcessDeletedEventId", + System.currentTimeMillis(), + processInstanceStarted + ) + ); + TaskImpl taskAssigned = new TaskImpl("1234-abc-5678-def", "task assigned", Task.TaskStatus.ASSIGNED); taskAssigned.setProcessDefinitionId("27"); taskAssigned.setProcessInstanceId("46"); diff --git a/activiti-cloud-audit-service/pom.xml b/activiti-cloud-audit-service/pom.xml index c589d21db13..8179ccf2a78 100644 --- a/activiti-cloud-audit-service/pom.xml +++ b/activiti-cloud-audit-service/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-audit-service-parent @@ -14,10 +14,13 @@ activiti-cloud-audit-dependencies activiti-cloud-services-audit-api + activiti-cloud-services-audit-consumer activiti-cloud-services-audit-model - activiti-cloud-services-audit-jpa + activiti-cloud-services-audit-rest activiti-cloud-services-audit-liquibase activiti-cloud-starter-audit + activiti-cloud-starter-audit-consumer + activiti-cloud-starter-audit-rest diff --git a/activiti-cloud-build/activiti-cloud-build-dependencies-parent/pom.xml b/activiti-cloud-build/activiti-cloud-build-dependencies-parent/pom.xml index 108f693e8fd..2b157468e87 100644 --- a/activiti-cloud-build/activiti-cloud-build-dependencies-parent/pom.xml +++ b/activiti-cloud-build/activiti-cloud-build-dependencies-parent/pom.xml @@ -6,16 +6,16 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-build-dependencies-parent pom Activiti Cloud :: Dependencies Parent - 2023.0.0 - 1.19.1 + 2023.0.3 + 1.20.1 2.2.224 - 21.3 + 22.1 42.7.2 4.24.0 diff --git a/activiti-cloud-build/pom.xml b/activiti-cloud-build/pom.xml index 9d56e3288e1..9f928a6a0a5 100644 --- a/activiti-cloud-build/pom.xml +++ b/activiti-cloud-build/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-mono-aggregator - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-build-parent pom diff --git a/activiti-cloud-connectors/activiti-cloud-connectors-dependencies/pom.xml b/activiti-cloud-connectors/activiti-cloud-connectors-dependencies/pom.xml index b1213acf3ea..8d13c9618f0 100755 --- a/activiti-cloud-connectors/activiti-cloud-connectors-dependencies/pom.xml +++ b/activiti-cloud-connectors/activiti-cloud-connectors-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-connectors-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-connectors-dependencies pom diff --git a/activiti-cloud-connectors/activiti-cloud-starter-connector/pom.xml b/activiti-cloud-connectors/activiti-cloud-starter-connector/pom.xml index 8e749707a50..793d948a13a 100644 --- a/activiti-cloud-connectors/activiti-cloud-starter-connector/pom.xml +++ b/activiti-cloud-connectors/activiti-cloud-starter-connector/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-connectors-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-connectors-dependencies activiti-cloud-starter-connector diff --git a/activiti-cloud-connectors/pom.xml b/activiti-cloud-connectors/pom.xml index 1149fe81604..99fe378e2f7 100644 --- a/activiti-cloud-connectors/pom.xml +++ b/activiti-cloud-connectors/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-connectors-parent diff --git a/activiti-cloud-dependencies/dependencies/pom.xml b/activiti-cloud-dependencies/dependencies/pom.xml index c1553a5c0d7..5acf11c5717 100644 --- a/activiti-cloud-dependencies/dependencies/pom.xml +++ b/activiti-cloud-dependencies/dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-dependencies-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-dependencies pom diff --git a/activiti-cloud-dependencies/pom.xml b/activiti-cloud-dependencies/pom.xml index 28d31e4df7c..9b82667e446 100644 --- a/activiti-cloud-dependencies/pom.xml +++ b/activiti-cloud-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-dependencies-parent diff --git a/activiti-cloud-examples/activiti-cloud-identity-adapter/pom.xml b/activiti-cloud-examples/activiti-cloud-identity-adapter/pom.xml index aeded488692..08947ae9565 100644 --- a/activiti-cloud-examples/activiti-cloud-identity-adapter/pom.xml +++ b/activiti-cloud-examples/activiti-cloud-identity-adapter/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-examples - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-identity-adapter Activiti Cloud :: Identity Adapter diff --git a/activiti-cloud-examples/activiti-cloud-query/Dockerfile b/activiti-cloud-examples/activiti-cloud-query/Dockerfile index 55eb7b43fc1..d7e155fd50d 100644 --- a/activiti-cloud-examples/activiti-cloud-query/Dockerfile +++ b/activiti-cloud-examples/activiti-cloud-query/Dockerfile @@ -22,6 +22,8 @@ RUN chmod +x ./entrypoint.sh COPY liquibase/target/*.jar liquibase.jar COPY starter/target/*.jar app.jar +COPY rest/target/*.jar rest.jar +COPY consumer/target/*.jar consumer.jar ENTRYPOINT ["./entrypoint.sh"] CMD ["-jar", "app.jar"] diff --git a/activiti-cloud-examples/activiti-cloud-query/config/pom.xml b/activiti-cloud-examples/activiti-cloud-query/config/pom.xml new file mode 100644 index 00000000000..c9ad349999f --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/config/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-build-parent + 8.7.0-SNAPSHOT + ../../../activiti-cloud-build/pom.xml + + + activiti-cloud-query-config + Activiti Cloud :: Query Config + + + true + ${java.version} + 21 + ${java.release} + ${project.version} + + + + + + org.activiti.cloud + activiti-cloud-query-dependencies + ${activiti-cloud.version} + import + pom + + + org.activiti.cloud + activiti-cloud-audit-dependencies + ${activiti-cloud.version} + import + pom + + + + + + org.springframework.boot + spring-boot + + + org.activiti.cloud + activiti-cloud-services-swagger + + + org.activiti + activiti-api-process-model + + + org.activiti + activiti-spring-security-policies + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/activiti-cloud-examples/activiti-cloud-query/starter/src/main/java/org/activiti/cloud/query/configuration/QueryConfiguration.java b/activiti-cloud-examples/activiti-cloud-query/config/src/main/java/org/activiti/cloud/query/configuration/QueryConfiguration.java similarity index 93% rename from activiti-cloud-examples/activiti-cloud-query/starter/src/main/java/org/activiti/cloud/query/configuration/QueryConfiguration.java rename to activiti-cloud-examples/activiti-cloud-query/config/src/main/java/org/activiti/cloud/query/configuration/QueryConfiguration.java index b9f364c5069..6ff141168e3 100644 --- a/activiti-cloud-examples/activiti-cloud-query/starter/src/main/java/org/activiti/cloud/query/configuration/QueryConfiguration.java +++ b/activiti-cloud-examples/activiti-cloud-query/config/src/main/java/org/activiti/cloud/query/configuration/QueryConfiguration.java @@ -25,15 +25,17 @@ import org.activiti.core.common.spring.security.policies.SecurityPoliciesRestrictionApplier; import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.info.BuildProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; -@Configuration +@AutoConfiguration public class QueryConfiguration { @Bean(name = "baseOpenApi") + @ConditionalOnMissingBean public OpenAPI baseOpenApi( BaseOpenApiBuilder baseOpenApiBuilder, @Value("${server.servlet.context-path:/}") String swaggerBasePath, diff --git a/activiti-cloud-examples/activiti-cloud-query/config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-examples/activiti-cloud-query/config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..8fd5ca8e6c3 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.activiti.cloud.query.configuration.QueryConfiguration diff --git a/activiti-cloud-examples/activiti-cloud-query/config/src/test/java/org/activiti/cloud/query/configuration/QueryConfigurationTest.java b/activiti-cloud-examples/activiti-cloud-query/config/src/test/java/org/activiti/cloud/query/configuration/QueryConfigurationTest.java new file mode 100644 index 00000000000..8ddbf46fd21 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/config/src/test/java/org/activiti/cloud/query/configuration/QueryConfigurationTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.query.configuration; + +import static org.mockito.Mockito.mock; + +import io.swagger.v3.oas.models.security.OAuthFlow; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.info.BuildProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.security.core.userdetails.UserDetailsService; + +@SpringBootTest +class QueryConfigurationTest { + + @SpringBootApplication + static class TestApplication { + + @Bean + OAuthFlow swaggerOAuthFlow() { + return mock(OAuthFlow.class); + } + } + + @MockBean + private BuildProperties buildProperties; + + @MockBean + private UserDetailsService userDetailsService; + + @Test + void contextLoads() {} +} diff --git a/activiti-cloud-examples/activiti-cloud-query/consumer/pom.xml b/activiti-cloud-examples/activiti-cloud-query/consumer/pom.xml new file mode 100644 index 00000000000..973af5e9372 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/consumer/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-query + 8.7.0-SNAPSHOT + + + activiti-cloud-query-starter-consumer + Activiti Cloud :: Query Starter Events Consumer + + + + org.activiti.cloud + activiti-cloud-starter-query-consumer + + + org.activiti.cloud + activiti-cloud-starter-audit-consumer + + + + + diff --git a/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/java/org/activiti/cloud/query/consumer/QueryConsumerApplication.java b/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/java/org/activiti/cloud/query/consumer/QueryConsumerApplication.java new file mode 100644 index 00000000000..d082157fed7 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/java/org/activiti/cloud/query/consumer/QueryConsumerApplication.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.query.consumer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class QueryConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(QueryConsumerApplication.class, args); + } +} diff --git a/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/resources/application.properties b/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/resources/application.properties new file mode 100644 index 00000000000..be6f1d0a628 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/resources/application.properties @@ -0,0 +1,30 @@ +spring.application.name=${ACT_QUERY_APP_NAME:query-consumer} + +# QUERY +spring.cloud.stream.bindings.producer.destination=${ACT_QUERY_PRODUCER_DEST:engineEvents} +spring.cloud.stream.bindings.producer.contentType=${ACT_QUERY_PRODUCER_CONTENT_TYPE:application/json} +spring.cloud.stream.bindings.queryConsumer.destination=${ACT_QUERY_CONSUMER_DEST:engineEvents} +spring.cloud.stream.bindings.queryConsumer.group=${ACT_QUERY_CONSUMER_GROUP:query} +spring.cloud.stream.bindings.queryConsumer.contentType=${ACT_QUERY_CONSUMER_CONTENT_TYPE:application/json} + +# AUDIT +spring.cloud.stream.bindings.auditConsumer.destination=${ACT_AUDIT_CONSUMER_DEST:engineEvents} +spring.cloud.stream.bindings.auditConsumer.group=${ACT_AUDIT_CONSUMER_GROUP:audit} +spring.cloud.stream.bindings.auditConsumer.contentType=${ACT_AUDIT_CONSUMER_CONTENT_TYPE:application/json} + +#for https://stackoverflow.com/questions/46493500/hibernate-with-c3p0-createclob-is-not-yet-implemented +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true + +spring.jackson.serialization.fail-on-unwrapped-type-identifiers=${ACT_QUERY_JACKSON_FAIL_ON_UNWRAPPED_IDS:false} + +spring.rabbitmq.host=${ACT_RABBITMQ_HOST:rabbitmq} +spring.rabbitmq.username=${ACT_RABBITMQ_USER:guest} +spring.rabbitmq.password=${ACT_RABBITMQ_PASS:guest} + +# zipkin (set spring.zipkin.enabled to true to activate) +spring.zipkin.enabled=false +spring.zipkin.base-url=http://zipkin:80/ +spring.zipkin.sender.type=web +management.tracing.sampling.probability=1.0 + +activiti.cloud.application.name=default-app diff --git a/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/resources/logback-spring.xml b/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/resources/logback-spring.xml new file mode 100644 index 00000000000..ef5b3abeeab --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/consumer/src/main/resources/logback-spring.xml @@ -0,0 +1,17 @@ + + + + + + logstash:5000 + + + + + + + + + + + diff --git a/activiti-cloud-examples/activiti-cloud-query/consumer/src/test/java/org/activiti/cloud/query/consumer/QueryConsumerApplicationIT.java b/activiti-cloud-examples/activiti-cloud-query/consumer/src/test/java/org/activiti/cloud/query/consumer/QueryConsumerApplicationIT.java new file mode 100644 index 00000000000..5f5552b9bc0 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/consumer/src/test/java/org/activiti/cloud/query/consumer/QueryConsumerApplicationIT.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.query.consumer; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(classes = { QueryConsumerApplication.class }) +public class QueryConsumerApplicationIT { + + @Test + public void contextLoads() throws Exception {} +} diff --git a/activiti-cloud-examples/activiti-cloud-query/liquibase/pom.xml b/activiti-cloud-examples/activiti-cloud-query/liquibase/pom.xml index 71c687f17ab..0128ba86e2a 100644 --- a/activiti-cloud-examples/activiti-cloud-query/liquibase/pom.xml +++ b/activiti-cloud-examples/activiti-cloud-query/liquibase/pom.xml @@ -3,7 +3,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../../../activiti-cloud-build/pom.xml activiti-cloud-query-liquibase @@ -12,7 +12,7 @@ true ${java.version} - 17 + 21 ${java.release} ${project.version} diff --git a/activiti-cloud-examples/activiti-cloud-query/pom.xml b/activiti-cloud-examples/activiti-cloud-query/pom.xml index d250071f490..e8764f2d904 100644 --- a/activiti-cloud-examples/activiti-cloud-query/pom.xml +++ b/activiti-cloud-examples/activiti-cloud-query/pom.xml @@ -6,39 +6,52 @@ org.activiti.cloud activiti-cloud-examples - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-query Activiti Cloud :: Query org.activiti.cloud.query.QueryApplication - 21.1 + 22.1 liquibase starter + rest + consumer + config + + + + org.activiti.cloud + activiti-cloud-query-config + ${project.version} + + + + org.activiti.cloud - activiti-cloud-starter-query - - - org.activiti.cloud - activiti-cloud-starter-audit + activiti-cloud-service-messaging-starter org.activiti.cloud - activiti-cloud-starter-notifications-graphql + activiti-cloud-services-tracing org.postgresql postgresql runtime + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + org.activiti.cloud @@ -74,8 +87,14 @@ test - com.fasterxml.jackson.dataformat - jackson-dataformat-yaml + org.activiti.cloud + activiti-cloud-services-test-containers + test + + + org.springframework.cloud + spring-cloud-stream-test-support + test diff --git a/activiti-cloud-examples/activiti-cloud-query/rest/pom.xml b/activiti-cloud-examples/activiti-cloud-query/rest/pom.xml new file mode 100644 index 00000000000..9ed9b8f28a0 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/rest/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-query + 8.7.0-SNAPSHOT + + + activiti-cloud-query-starter-rest + Activiti Cloud :: Query Starter Rest Api + + + + org.activiti.cloud + activiti-cloud-query-config + + + org.activiti.cloud + activiti-cloud-starter-query-rest + + + org.activiti.cloud + activiti-cloud-starter-audit-rest + + + org.activiti.cloud + activiti-cloud-starter-notifications-graphql + + + + diff --git a/activiti-cloud-examples/activiti-cloud-query/rest/src/main/java/org/activiti/cloud/query/rest/QueryRestApplication.java b/activiti-cloud-examples/activiti-cloud-query/rest/src/main/java/org/activiti/cloud/query/rest/QueryRestApplication.java new file mode 100644 index 00000000000..e56264b7315 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/rest/src/main/java/org/activiti/cloud/query/rest/QueryRestApplication.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.query.rest; + +import org.activiti.cloud.starter.audit.configuration.EnableActivitiAudit; +import org.activiti.cloud.starter.query.configuration.EnableActivitiQuery; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableActivitiQuery +@EnableActivitiAudit +public class QueryRestApplication { + + public static void main(String[] args) { + SpringApplication.run(QueryRestApplication.class, args); + } +} diff --git a/activiti-cloud-examples/activiti-cloud-query/rest/src/main/resources/application.properties b/activiti-cloud-examples/activiti-cloud-query/rest/src/main/resources/application.properties new file mode 100644 index 00000000000..6273ddb29b6 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/rest/src/main/resources/application.properties @@ -0,0 +1,30 @@ +spring.application.name=${ACT_QUERY_APP_NAME:query} + +#for https://stackoverflow.com/questions/46493500/hibernate-with-c3p0-createclob-is-not-yet-implemented +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true + +spring.jackson.serialization.fail-on-unwrapped-type-identifiers=${ACT_QUERY_JACKSON_FAIL_ON_UNWRAPPED_IDS:false} + +authorizations.security-constraints[0].authRoles[0]=${ACT_KEYCLOAK_USER_ROLE:ACTIVITI_USER} +authorizations.security-constraints[0].securityCollections[0].patterns[0]=${ACT_KEYCLOAK_PATTERNS:/v1/*} +authorizations.security-constraints[1].authRoles[0]=${ACT_KEYCLOAK_ADMIN_ROLE:ACTIVITI_ADMIN} +authorizations.security-constraints[1].securityCollections[0].patterns[0]=/admin/* + +spring.rabbitmq.host=${ACT_RABBITMQ_HOST:rabbitmq} +spring.rabbitmq.username=${ACT_RABBITMQ_USER:guest} +spring.rabbitmq.password=${ACT_RABBITMQ_PASS:guest} + +# zipkin (set spring.zipkin.enabled to true to activate) +spring.zipkin.enabled=false +spring.zipkin.base-url=http://zipkin:80/ +spring.zipkin.sender.type=web +management.tracing.sampling.probability=1.0 + +activiti.cloud.application.name=default-app + +springdoc.swagger-ui.urls[0].url=/audit/v3/api-docs/Audit +springdoc.swagger-ui.urls[0].name=Audit +springdoc.swagger-ui.urls[1].url=/query/v3/api-docs/Query +springdoc.swagger-ui.urls[1].name=Query +springdoc.swagger-ui.config-url=/query/v3/api-docs/swagger-config +springdoc.swagger-ui.oauth2-redirect-url=/query/swagger-ui/oauth2-redirect.html diff --git a/activiti-cloud-examples/activiti-cloud-query/rest/src/main/resources/logback-spring.xml b/activiti-cloud-examples/activiti-cloud-query/rest/src/main/resources/logback-spring.xml new file mode 100644 index 00000000000..ef5b3abeeab --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/rest/src/main/resources/logback-spring.xml @@ -0,0 +1,17 @@ + + + + + + logstash:5000 + + + + + + + + + + + diff --git a/activiti-cloud-examples/activiti-cloud-query/rest/src/test/java/org/activiti/cloud/query/rest/QueryRestApplicationIT.java b/activiti-cloud-examples/activiti-cloud-query/rest/src/test/java/org/activiti/cloud/query/rest/QueryRestApplicationIT.java new file mode 100644 index 00000000000..9d7efe59b88 --- /dev/null +++ b/activiti-cloud-examples/activiti-cloud-query/rest/src/test/java/org/activiti/cloud/query/rest/QueryRestApplicationIT.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.query.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.both; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.activiti.cloud.services.test.containers.KeycloakContainerApplicationInitializer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@SpringBootTest(classes = { QueryRestApplication.class }) +@WebAppConfiguration +@ContextConfiguration(initializers = { KeycloakContainerApplicationInitializer.class }) +public class QueryRestApplicationIT { + + @Autowired + private WebApplicationContext context; + + @Autowired + private ApplicationContext applicationContext; + + @Test + public void contextLoads() throws Exception { + assertThat(applicationContext).isNotNull(); + } + + @Test + public void defaultSpecificationFileShouldBeAlfrescoFormat() throws Exception { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); + mockMvc + .perform(MockMvcRequestBuilders.get("/v3/api-docs/Query").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect( + content() + .string( + both(notNullValue(String.class)) + .and(containsString("ListResponseContentCloudProcessDefinition")) + .and(containsString("EntriesResponseContentCloudProcessDefinition")) + .and(containsString("EntryResponseContentCloudProcessDefinition")) + .and(not(containsString("PagedModel"))) + .and(not(containsString("ResourcesOfResource"))) + .and(not(containsString("Resource"))) + ) + ); + } +} diff --git a/activiti-cloud-examples/activiti-cloud-query/starter/pom.xml b/activiti-cloud-examples/activiti-cloud-query/starter/pom.xml index 29c4981d0eb..8ab0abc8cc5 100644 --- a/activiti-cloud-examples/activiti-cloud-query/starter/pom.xml +++ b/activiti-cloud-examples/activiti-cloud-query/starter/pom.xml @@ -5,30 +5,29 @@ activiti-cloud-query org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT 4.0.0 activiti-cloud-query-starter + Activiti Cloud :: Query Starter All-In-One org.activiti.cloud - activiti-cloud-service-messaging-starter + activiti-cloud-query-config org.activiti.cloud - activiti-cloud-services-tracing + activiti-cloud-starter-query org.activiti.cloud - activiti-cloud-services-test-containers - test + activiti-cloud-starter-audit - org.springframework.cloud - spring-cloud-stream-test-support - test + org.activiti.cloud + activiti-cloud-starter-notifications-graphql diff --git a/activiti-cloud-examples/example-cloud-connector/pom.xml b/activiti-cloud-examples/example-cloud-connector/pom.xml index 2211e9ec646..8a59b23d883 100644 --- a/activiti-cloud-examples/example-cloud-connector/pom.xml +++ b/activiti-cloud-examples/example-cloud-connector/pom.xml @@ -9,7 +9,7 @@ org.activiti.cloud activiti-cloud-examples - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT example-cloud-connector Activiti Cloud :: Example Cloud Connector diff --git a/activiti-cloud-examples/example-cloud-connector/starter/pom.xml b/activiti-cloud-examples/example-cloud-connector/starter/pom.xml index 1ca4cf8a160..da8224f62be 100644 --- a/activiti-cloud-examples/example-cloud-connector/starter/pom.xml +++ b/activiti-cloud-examples/example-cloud-connector/starter/pom.xml @@ -5,7 +5,7 @@ example-cloud-connector org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT 4.0.0 diff --git a/activiti-cloud-examples/example-runtime-bundle/pom.xml b/activiti-cloud-examples/example-runtime-bundle/pom.xml index 39d46fda377..1b792a37b98 100644 --- a/activiti-cloud-examples/example-runtime-bundle/pom.xml +++ b/activiti-cloud-examples/example-runtime-bundle/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-examples - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT example-runtime-bundle Activiti Cloud :: Runtime Bundle diff --git a/activiti-cloud-examples/example-runtime-bundle/starter/pom.xml b/activiti-cloud-examples/example-runtime-bundle/starter/pom.xml index 2f183c79b96..2ed3df81386 100644 --- a/activiti-cloud-examples/example-runtime-bundle/starter/pom.xml +++ b/activiti-cloud-examples/example-runtime-bundle/starter/pom.xml @@ -5,7 +5,7 @@ example-runtime-bundle org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT 4.0.0 diff --git a/activiti-cloud-examples/pom.xml b/activiti-cloud-examples/pom.xml index b7c7284d924..853250424a6 100644 --- a/activiti-cloud-examples/pom.xml +++ b/activiti-cloud-examples/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-examples diff --git a/activiti-cloud-messages-service/dependencies/pom.xml b/activiti-cloud-messages-service/dependencies/pom.xml index 734b4a9a4ef..d53291e628a 100644 --- a/activiti-cloud-messages-service/dependencies/pom.xml +++ b/activiti-cloud-messages-service/dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-messages-service-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-messages-dependencies pom diff --git a/activiti-cloud-messages-service/integration-tests/pom.xml b/activiti-cloud-messages-service/integration-tests/pom.xml index 335f27908ae..52fd2e31e8e 100644 --- a/activiti-cloud-messages-service/integration-tests/pom.xml +++ b/activiti-cloud-messages-service/integration-tests/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-messages-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../dependencies activiti-cloud-messages-integration-tests diff --git a/activiti-cloud-messages-service/pom.xml b/activiti-cloud-messages-service/pom.xml index 5a591d5c4d2..662d6cd0f79 100644 --- a/activiti-cloud-messages-service/pom.xml +++ b/activiti-cloud-messages-service/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-messages-service-parent diff --git a/activiti-cloud-messages-service/services/core/pom.xml b/activiti-cloud-messages-service/services/core/pom.xml index a5d2e67c133..1cd0a254c48 100644 --- a/activiti-cloud-messages-service/services/core/pom.xml +++ b/activiti-cloud-messages-service/services/core/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-messages - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT Activiti Cloud Services :: Messages Core activiti-cloud-services-messages-core diff --git a/activiti-cloud-messages-service/services/pom.xml b/activiti-cloud-messages-service/services/pom.xml index a3402a89756..34941817fdd 100644 --- a/activiti-cloud-messages-service/services/pom.xml +++ b/activiti-cloud-messages-service/services/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-messages-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../dependencies activiti-cloud-services-messages diff --git a/activiti-cloud-messages-service/services/tests/pom.xml b/activiti-cloud-messages-service/services/tests/pom.xml index 516dced9314..4636dc0568c 100644 --- a/activiti-cloud-messages-service/services/tests/pom.xml +++ b/activiti-cloud-messages-service/services/tests/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-messages - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-messages-tests diff --git a/activiti-cloud-messages-service/starters/hazelcast/pom.xml b/activiti-cloud-messages-service/starters/hazelcast/pom.xml index e6fc2bb0f80..f7c2b1977ec 100644 --- a/activiti-cloud-messages-service/starters/hazelcast/pom.xml +++ b/activiti-cloud-messages-service/starters/hazelcast/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-starters-messages - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-starter-messages-hazelcast Activiti Cloud Starter :: Messages Hazelcast diff --git a/activiti-cloud-messages-service/starters/jdbc/pom.xml b/activiti-cloud-messages-service/starters/jdbc/pom.xml index 00100a50105..9044d670d99 100644 --- a/activiti-cloud-messages-service/starters/jdbc/pom.xml +++ b/activiti-cloud-messages-service/starters/jdbc/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-starters-messages - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-starter-messages-jdbc Activiti Cloud Starter :: Messages JDBC diff --git a/activiti-cloud-messages-service/starters/pom.xml b/activiti-cloud-messages-service/starters/pom.xml index aadb4d8f6fd..c777d870fcf 100644 --- a/activiti-cloud-messages-service/starters/pom.xml +++ b/activiti-cloud-messages-service/starters/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-messages-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../dependencies activiti-cloud-starters-messages diff --git a/activiti-cloud-messages-service/starters/redis/pom.xml b/activiti-cloud-messages-service/starters/redis/pom.xml index ab2f1aaddb2..84a434414b2 100644 --- a/activiti-cloud-messages-service/starters/redis/pom.xml +++ b/activiti-cloud-messages-service/starters/redis/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-starters-messages - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-starter-messages-redis Activiti Cloud Starter :: Messages Redis diff --git a/activiti-cloud-notifications-graphql-service/dependencies/pom.xml b/activiti-cloud-notifications-graphql-service/dependencies/pom.xml index 98ead20b644..e70cc5e0ae4 100644 --- a/activiti-cloud-notifications-graphql-service/dependencies/pom.xml +++ b/activiti-cloud-notifications-graphql-service/dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-notifications-service-graphql-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT Activiti Cloud Notifications :: GraphQL Dependencies (Bill Of Materials) activiti-cloud-notifications-graphql-dependencies @@ -83,6 +83,11 @@ ${querydsl.version} jakarta + + io.github.classgraph + classgraph + ${classgraph.version} + diff --git a/activiti-cloud-notifications-graphql-service/pom.xml b/activiti-cloud-notifications-graphql-service/pom.xml index fc8395dce71..2de54ded37f 100644 --- a/activiti-cloud-notifications-graphql-service/pom.xml +++ b/activiti-cloud-notifications-graphql-service/pom.xml @@ -5,14 +5,14 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-notifications-service-graphql-parent Activiti Cloud Notifications GraphQL Service :: Parent pom - 1.2.5 + 1.2.10 diff --git a/activiti-cloud-notifications-graphql-service/services/api/pom.xml b/activiti-cloud-notifications-graphql-service/services/api/pom.xml index 81897cea7b3..6d00e743c44 100644 --- a/activiti-cloud-notifications-graphql-service/services/api/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/api/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-api Activiti Cloud Notifications :: Services :: GraphQL Api diff --git a/activiti-cloud-notifications-graphql-service/services/events/pom.xml b/activiti-cloud-notifications-graphql-service/services/events/pom.xml index 6ea50d2436e..62d4b7f0745 100644 --- a/activiti-cloud-notifications-graphql-service/services/events/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/events/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-events Activiti Cloud Notifications :: Services :: GraphQL Events diff --git a/activiti-cloud-notifications-graphql-service/services/graphiql/pom.xml b/activiti-cloud-notifications-graphql-service/services/graphiql/pom.xml index 23f6ba39587..f3a5bb69b09 100644 --- a/activiti-cloud-notifications-graphql-service/services/graphiql/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/graphiql/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-graphiql Activiti Cloud Notifications :: Services :: GraphiQL Client diff --git a/activiti-cloud-notifications-graphql-service/services/jpa-query/pom.xml b/activiti-cloud-notifications-graphql-service/services/jpa-query/pom.xml index 252034f2fee..0b0808aa75e 100644 --- a/activiti-cloud-notifications-graphql-service/services/jpa-query/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/jpa-query/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-jpa-query Activiti Cloud Notifications :: Services :: GraphQL Jpa Query diff --git a/activiti-cloud-notifications-graphql-service/services/jpa-query/src/main/java/org/activiti/cloud/services/notifications/graphql/jpa/query/ActivitiGraphQLSchemaAutoConfiguration.java b/activiti-cloud-notifications-graphql-service/services/jpa-query/src/main/java/org/activiti/cloud/services/notifications/graphql/jpa/query/ActivitiGraphQLSchemaAutoConfiguration.java index 0b0f7ae738a..32926008f3f 100644 --- a/activiti-cloud-notifications-graphql-service/services/jpa-query/src/main/java/org/activiti/cloud/services/notifications/graphql/jpa/query/ActivitiGraphQLSchemaAutoConfiguration.java +++ b/activiti-cloud-notifications-graphql-service/services/jpa-query/src/main/java/org/activiti/cloud/services/notifications/graphql/jpa/query/ActivitiGraphQLSchemaAutoConfiguration.java @@ -21,8 +21,10 @@ import com.introproventures.graphql.jpa.query.autoconfigure.GraphQLJPASchemaBuilderCustomizer; import com.introproventures.graphql.jpa.query.schema.JavaScalars; import graphql.GraphQL; +import java.util.Optional; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.model.VariableValue; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -40,18 +42,32 @@ @EnableGraphQLJpaQuerySchema(basePackageClasses = ProcessInstanceEntity.class) public class ActivitiGraphQLSchemaAutoConfiguration { + @Value("${spring.activiti.cloud.services.notifications.graphql.jpa-query.aggregate.enabled:true}") + private boolean isAggregateEnabled; + @Bean GraphQLJPASchemaBuilderCustomizer graphQLJPASchemaBuilderCustomizer() { return builder -> builder .name("Query") .description("Activiti Cloud Query Schema") + .enableAggregate(isAggregateEnabled) .scalar( VariableValue.class, newScalar() .name("VariableValue") - .description("VariableValue type") - .coercing(new JavaScalars.GraphQLObjectCoercing()) + .coercing( + new JavaScalars.GraphQLObjectCoercing() { + public Object serialize(final Object input) { + return Optional + .ofNullable(input) + .filter(VariableValue.class::isInstance) + .map(VariableValue.class::cast) + .map(it -> Optional.ofNullable(it.getValue()).orElse(Optional.empty())) + .orElseGet(() -> super.serialize(input)); + } + } + ) .build() ); } diff --git a/activiti-cloud-notifications-graphql-service/services/jpa-query/src/test/resources/data.sql b/activiti-cloud-notifications-graphql-service/services/jpa-query/src/test/resources/data.sql index fda6c1a91f6..66e52bd3c22 100644 --- a/activiti-cloud-notifications-graphql-service/services/jpa-query/src/test/resources/data.sql +++ b/activiti-cloud-notifications-graphql-service/services/jpa-query/src/test/resources/data.sql @@ -1,18 +1,62 @@ -insert into process_instance (id, last_modified, last_modified_from, last_modified_to, process_definition_id, status, initiator, start_date, business_key, process_definition_key) values +/* Using "JSONB" data type for value column in PROCESS_VARIABLE and TASK_VARIABLE tables, +the automatic creation of tables is not working anymore with H2 database which only supports "JSON". +So, these two tables have to be created manually */ +CREATE TABLE IF NOT EXISTS PROCESS_VARIABLE ( + marked_as_deleted BOOLEAN, + create_time TIMESTAMP(6), + id BIGINT NOT NULL, + last_updated_time TIMESTAMP(6), + app_name VARCHAR(255), + app_version VARCHAR(255), + execution_id VARCHAR(255), + name VARCHAR(255), + process_definition_key VARCHAR(255), + process_instance_id VARCHAR(255), + service_full_name VARCHAR(255), + service_name VARCHAR(255), + service_type VARCHAR(255), + service_version VARCHAR(255), + type VARCHAR(255), + variable_definition_id VARCHAR(255), + "value" JSON, + PRIMARY KEY (id) +); + +CREATE TABLE IF NOT EXISTS TASK_VARIABLE ( + marked_as_deleted BOOLEAN, + create_time TIMESTAMP(6), + id BIGINT NOT NULL, + last_updated_time TIMESTAMP(6), + app_name VARCHAR(255), + app_version VARCHAR(255), + execution_id VARCHAR(255), + name VARCHAR(255), + process_instance_id VARCHAR(255), + service_full_name VARCHAR(255), + service_name VARCHAR(255), + service_type VARCHAR(255), + service_version VARCHAR(255), + task_id VARCHAR(255), + type VARCHAR(255), + "value" JSON, + PRIMARY KEY (id) +); + +INSERT INTO process_instance (id, last_modified, last_modified_from, last_modified_to, process_definition_id, status, initiator, start_date, business_key, process_definition_key) VALUES ('0', CURRENT_TIMESTAMP, null, null, 'process_definition_id', 'RUNNING', 'initiator',null, 'bus_key','def_key'), ('1', CURRENT_TIMESTAMP, null, null, 'process_definition_id', 'RUNNING', 'initiator',null, 'bus_key','def_key'); -insert into task (id, assignee, created_date, description, due_date, last_modified, last_modified_from, last_modified_to, name, priority, process_definition_id, process_instance_id, status, owner, claimed_date) values +INSERT INTO task (id, assignee, created_date, description, due_date, last_modified, last_modified_from, last_modified_to, name, priority, process_definition_id, process_instance_id, status, owner, claimed_date) VALUES ('1', 'assignee', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task1', 5, 'process_definition_id', 0, 'COMPLETED' , 'owner', null), ('2', 'assignee', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task2', 10, 'process_definition_id', 0, 'CREATED' , 'owner', null), ('3', 'assignee', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task3', 5, 'process_definition_id', 0, 'CREATED' , 'owner', null), ('4', 'assignee', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task4', 10, 'process_definition_id', 1, 'CREATED' , 'owner', null), ('5', 'assignee', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task5', 5, 'process_definition_id', 1, 'COMPLETED' , 'owner', null); -insert into PROCESS_VARIABLE (id,create_time, execution_id, last_updated_time, name, process_instance_id, type, "value") values +INSERT INTO PROCESS_VARIABLE (id,create_time, execution_id, last_updated_time, name, process_instance_id, type, "value") VALUES (1,CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'initiator', 1, 'map', '{"value": { "key" : ["1","2","3","4","5"]}}'); -insert into TASK_VARIABLE (id, create_time, execution_id, last_updated_time, name, process_instance_id, task_id, type, "value") values +INSERT INTO TASK_VARIABLE (id, create_time, execution_id, last_updated_time, name, process_instance_id, task_id, type, "value") VALUES (2, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable1', 0, '1', 'String', '{"value": "10"}'), (3, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable2', 0, '1', 'String', '{"value": true}'), (4, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable3', 0, '2', 'String', '{"value": null}'), diff --git a/activiti-cloud-notifications-graphql-service/services/pom.xml b/activiti-cloud-notifications-graphql-service/services/pom.xml index c76a6700e7c..7776134fa3b 100644 --- a/activiti-cloud-notifications-graphql-service/services/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-notifications-graphql-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../dependencies activiti-cloud-services-notifications-graphql diff --git a/activiti-cloud-notifications-graphql-service/services/schema/pom.xml b/activiti-cloud-notifications-graphql-service/services/schema/pom.xml index 7cfed5380da..3c922721302 100644 --- a/activiti-cloud-notifications-graphql-service/services/schema/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/schema/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-schema Activiti Cloud Notifications :: Services :: GraphQL Schema diff --git a/activiti-cloud-notifications-graphql-service/services/security/pom.xml b/activiti-cloud-notifications-graphql-service/services/security/pom.xml index 631b18c6b41..e3f75153363 100644 --- a/activiti-cloud-notifications-graphql-service/services/security/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/security/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-security Activiti Cloud Notifications :: Services :: GraphQL Security diff --git a/activiti-cloud-notifications-graphql-service/services/subscriptions/pom.xml b/activiti-cloud-notifications-graphql-service/services/subscriptions/pom.xml index fb650d5b6a2..f4794267c55 100644 --- a/activiti-cloud-notifications-graphql-service/services/subscriptions/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/subscriptions/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-subscriptions Activiti Cloud Notifications :: Services :: GraphQL Subscriptions diff --git a/activiti-cloud-notifications-graphql-service/services/subscriptions/src/main/java/org/activiti/cloud/services/notifications/graphql/subscriptions/GraphQLSubscriptionSchemaBuilder.java b/activiti-cloud-notifications-graphql-service/services/subscriptions/src/main/java/org/activiti/cloud/services/notifications/graphql/subscriptions/GraphQLSubscriptionSchemaBuilder.java index 13c90e86c59..cfeea0ecf31 100644 --- a/activiti-cloud-notifications-graphql-service/services/subscriptions/src/main/java/org/activiti/cloud/services/notifications/graphql/subscriptions/GraphQLSubscriptionSchemaBuilder.java +++ b/activiti-cloud-notifications-graphql-service/services/subscriptions/src/main/java/org/activiti/cloud/services/notifications/graphql/subscriptions/GraphQLSubscriptionSchemaBuilder.java @@ -64,12 +64,12 @@ public GraphQLSubscriptionSchemaBuilder(String schemaFileName) { .coercing(new JavaScalars.GraphQLObjectCoercing()) .build() ) - .scalar(ExtendedScalars.GraphQLLong) - .transformer(new JavaScalarsWiringPostProcessor()); + .scalar(ExtendedScalars.GraphQLLong); } private GraphQLSchema buildSchema() { - return new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring.build()); + return new JavaScalarsWiringPostProcessor() + .process(new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring.build())); } public TypeRuntimeWiring.Builder withTypeWiring(String typeName) { diff --git a/activiti-cloud-notifications-graphql-service/services/web/pom.xml b/activiti-cloud-notifications-graphql-service/services/web/pom.xml index a9567d6b7cd..781275f66b2 100644 --- a/activiti-cloud-notifications-graphql-service/services/web/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/web/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-web Activiti Cloud Notifications :: Services :: GraphQL Web diff --git a/activiti-cloud-notifications-graphql-service/services/ws/pom.xml b/activiti-cloud-notifications-graphql-service/services/ws/pom.xml index 58826b8416b..49d1349abe4 100644 --- a/activiti-cloud-notifications-graphql-service/services/ws/pom.xml +++ b/activiti-cloud-notifications-graphql-service/services/ws/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-services-notifications-graphql - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-notifications-graphql-ws Activiti Cloud Notifications :: Services :: GraphQL WebSockets @@ -18,6 +18,7 @@ io.dropwizard.metrics metrics-annotation + 4.2.26 org.springframework.boot diff --git a/activiti-cloud-notifications-graphql-service/starter/pom.xml b/activiti-cloud-notifications-graphql-service/starter/pom.xml index 0b3fc18d92f..285186b0a48 100644 --- a/activiti-cloud-notifications-graphql-service/starter/pom.xml +++ b/activiti-cloud-notifications-graphql-service/starter/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-notifications-graphql-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../dependencies activiti-cloud-starter-notifications-graphql diff --git a/activiti-cloud-notifications-graphql-service/starter/src/test/java/org/activiti/cloud/notifications/graphql/starter/ActivitiGraphQLStarterIT.java b/activiti-cloud-notifications-graphql-service/starter/src/test/java/org/activiti/cloud/notifications/graphql/starter/ActivitiGraphQLStarterIT.java index 034ea8b8963..12ad10b560a 100644 --- a/activiti-cloud-notifications-graphql-service/starter/src/test/java/org/activiti/cloud/notifications/graphql/starter/ActivitiGraphQLStarterIT.java +++ b/activiti-cloud-notifications-graphql-service/starter/src/test/java/org/activiti/cloud/notifications/graphql/starter/ActivitiGraphQLStarterIT.java @@ -1418,6 +1418,113 @@ public void testGraphqlArguments() { assertThat("{Tasks={select=[{id=1, assignee=assignee, priority=5}]}}").isEqualTo(result.getData().toString()); } + @Test + public void testGraphqlAggregateTaskVariablesQuery() { + GraphQLQueryRequest query = new GraphQLQueryRequest( + """ + query { + TaskVariables( + # Apply filter criteria + where: {name: {IN: ["variable1", "variable2", "variable3"]}} + ) { + aggregate { + # count by variables + variables: count + # Count by associated tasks + groupByVariableName: group { + name: by(field: name) + count + } + by { + groupByTaskStatus: task { + status: by(field: status) + count + } + # Count by associated tasks + groupByTaskAssignee: task { + assignee: by(field: assignee) + count + } + } + } + } + } + """ + ); + + ResponseEntity entity = rest.postForEntity( + GRAPHQL_URL, + new HttpEntity<>(query, authHeaders), + GraphQLQueryResult.class + ); + + assertThat(entity.getStatusCode()).describedAs(entity.toString()).isEqualTo(HttpStatus.OK); + + GraphQLQueryResult result = entity.getBody(); + + assertThat(result).isNotNull(); + assertThat(result.getErrors()).isNull(); + + var expected = + "{TaskVariables={aggregate={variables=3, groupByVariableName=[{name=variable1, count=1}, {name=variable2, count=1}, {name=variable3, count=1}], by={groupByTaskStatus=[{status=COMPLETED, count=2}, {status=CREATED, count=1}], groupByTaskAssignee=[{assignee=assignee, count=3}]}}}}"; + + assertThat(result.getData().toString()).isEqualTo(expected); + } + + @Test + public void testGraphqlAggregateTasksQuery() { + GraphQLQueryRequest query = new GraphQLQueryRequest( + """ + query { + Tasks { + aggregate { + countTasks: count + countProcessVariables: count(of: processVariables) + countTaskVariables: count(of: variables) + countTasksGroupedByStatus: group { + status: by(field: status) + count + } + countProcessVariablesGroupedByTaskName: group { + name: by(field: name) + count(of: processVariables) + } + by { + countTaskProcessVariablesGroupedByVariableNameAndValue: processVariables { + name: by(field: name) + value: by(field: value) + count + } + countTaskVariablesGroupedByVariableName: variables { + name: by(field: name) + count + } + } + } + } + } + """ + ); + + ResponseEntity entity = rest.postForEntity( + GRAPHQL_URL, + new HttpEntity<>(query, authHeaders), + GraphQLQueryResult.class + ); + + assertThat(entity.getStatusCode()).describedAs(entity.toString()).isEqualTo(HttpStatus.OK); + + GraphQLQueryResult result = entity.getBody(); + + assertThat(result).isNotNull(); + assertThat(result.getErrors()).isNull(); + + var expected = + "{Tasks={aggregate={countTasks=6, countProcessVariables=2, countTaskVariables=6, countTasksGroupedByStatus=[{status=ASSIGNED, count=1}, {status=COMPLETED, count=2}, {status=CREATED, count=3}], countProcessVariablesGroupedByTaskName=[{name=task4, count=1}, {name=task5, count=1}], by={countTaskProcessVariablesGroupedByVariableNameAndValue=[{name=initiator, value={key=[1, 2, 3, 4, 5]}, count=2}], countTaskVariablesGroupedByVariableName=[{name=variable1, count=1}, {name=variable2, count=1}, {name=variable3, count=1}, {name=variable4, count=1}, {name=variable5, count=1}, {name=variable6, count=1}]}}}}"; + + assertThat(result.getData().toString()).isEqualTo(expected); + } + public static StringObjectMapBuilder mapBuilder() { return new StringObjectMapBuilder(); } diff --git a/activiti-cloud-notifications-graphql-service/starter/src/test/resources/data.sql b/activiti-cloud-notifications-graphql-service/starter/src/test/resources/data.sql index f30f5cc3bfb..20a6cfc5e08 100644 --- a/activiti-cloud-notifications-graphql-service/starter/src/test/resources/data.sql +++ b/activiti-cloud-notifications-graphql-service/starter/src/test/resources/data.sql @@ -1,8 +1,52 @@ -insert into process_instance (id, last_modified, last_modified_from, last_modified_to, process_definition_id, status, initiator, start_date, business_key, process_definition_key) values +/* Using "JSONB" data type for value column in PROCESS_VARIABLE and TASK_VARIABLE tables, +the automatic creation of tables is not working anymore with H2 database which only supports "JSON". +So, these two tables have to be created manually */ +CREATE TABLE IF NOT EXISTS PROCESS_VARIABLE ( + marked_as_deleted BOOLEAN, + create_time TIMESTAMP(6), + id BIGINT NOT NULL, + last_updated_time TIMESTAMP(6), + app_name VARCHAR(255), + app_version VARCHAR(255), + execution_id VARCHAR(255), + name VARCHAR(255), + process_definition_key VARCHAR(255), + process_instance_id VARCHAR(255), + service_full_name VARCHAR(255), + service_name VARCHAR(255), + service_type VARCHAR(255), + service_version VARCHAR(255), + type VARCHAR(255), + variable_definition_id VARCHAR(255), + "value" JSON, + PRIMARY KEY (id) +); + +CREATE TABLE IF NOT EXISTS TASK_VARIABLE ( + marked_as_deleted BOOLEAN, + create_time TIMESTAMP(6), + id BIGINT NOT NULL, + last_updated_time TIMESTAMP(6), + app_name VARCHAR(255), + app_version VARCHAR(255), + execution_id VARCHAR(255), + name VARCHAR(255), + process_instance_id VARCHAR(255), + service_full_name VARCHAR(255), + service_name VARCHAR(255), + service_type VARCHAR(255), + service_version VARCHAR(255), + task_id VARCHAR(255), + type VARCHAR(255), + "value" JSON, + PRIMARY KEY (id) +); + +INSERT INTO process_instance (id, last_modified, last_modified_from, last_modified_to, process_definition_id, status, initiator, start_date, business_key, process_definition_key) VALUES ('0', CURRENT_TIMESTAMP, null, null, 'process_definition_id', 'RUNNING', 'initiator',null, 'bus_key','def_key'), ('1', CURRENT_TIMESTAMP, null, null, 'process_definition_id', 'RUNNING', 'initiator',null, 'bus_key','def_key'); -insert into task (id, assignee, business_key, created_date, description, due_date, last_modified, last_modified_from, last_modified_to, name, priority, process_definition_id, process_instance_id, status, owner, claimed_date) values +INSERT INTO task (id, assignee, business_key, created_date, description, due_date, last_modified, last_modified_from, last_modified_to, name, priority, process_definition_id, process_instance_id, status, owner, claimed_date) VALUES ('1', 'assignee', 'bk1', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task1', 5, 'process_definition_id', 0, 'COMPLETED' , 'owner', null), ('2', 'assignee', null, CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task2', 10, 'process_definition_id', 0, 'CREATED' , 'owner', null), ('3', 'assignee', null, CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task3', 5, 'process_definition_id', 0, 'CREATED' , 'owner', null), @@ -10,13 +54,17 @@ insert into task (id, assignee, business_key, created_date, description, due_dat ('5', 'assignee', null, CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task5', 10, 'process_definition_id', 1, 'COMPLETED' , 'owner', null), ('6', 'assignee', 'bk6', CURRENT_TIMESTAMP, 'description', null, null, null, null, 'task6', 10, 'process_definition_id', 0, 'ASSIGNED' , 'owner', null); -insert into PROCESS_VARIABLE (id, create_time, execution_id, last_updated_time, name, process_instance_id, type, "value") values - (1, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'initiator', 1, 'map', '{"value": { "key" : ["1","2","3","4","5"]}}'); +INSERT INTO PROCESS_VARIABLE (id, create_time, execution_id, last_updated_time, name, process_instance_id, type, "value") VALUES + (1, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'initiator', 1, 'map', JSON '{"value": { "key" : ["1","2","3","4","5"]}}'); + +INSERT INTO TASK_VARIABLE (id, create_time, execution_id, last_updated_time, name, process_instance_id, task_id, type, "value") VALUES + (2, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable1', 0, '1', 'String', JSON '{"value": "10"}'), + (3, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable2', 0, '1', 'String', JSON '{"value": true}'), + (4, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable3', 0, '2', 'String', JSON '{"value": null}'), + (5, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable4', 0, '2', 'map', JSON '{"value": { "key" : "data" }}'), + (6, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable5', 1, '4', 'String', JSON '{"value": 1.0}'), + (7, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable6', 1, '4', 'list', JSON '{"value": [1,2,3,4,5]}'); -insert into TASK_VARIABLE (id, create_time, execution_id, last_updated_time, name, process_instance_id, task_id, type, "value") values - (2, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable1', 0, '1', 'String', '{"value": "10"}'), - (3, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable2', 0, '1', 'String', '{"value": true}'), - (4, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable3', 0, '2', 'String', '{"value": null}'), - (5, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable4', 0, '2', 'map', '{"value": { "key" : "data" }}'), - (6, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable5', 1, '4', 'String', '{"value": 1.0}'), - (7, CURRENT_TIMESTAMP, 'execution_id', CURRENT_TIMESTAMP, 'variable6', 1, '4', 'list', '{"value": [1,2,3,4,5]}'); +INSERT INTO TASK_PROCESS_VARIABLE (task_id, process_variable_id) VALUES + (4,1), + (5,1); diff --git a/activiti-cloud-query-service/activiti-cloud-query-dependencies/pom.xml b/activiti-cloud-query-service/activiti-cloud-query-dependencies/pom.xml index b9fb1f39e21..a024a77cf0a 100755 --- a/activiti-cloud-query-service/activiti-cloud-query-dependencies/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-query-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-query-service-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-query-dependencies pom @@ -25,6 +25,11 @@ activiti-cloud-services-query-model ${project.version} + + org.activiti.cloud + activiti-cloud-services-query-events + ${project.version} + org.activiti.cloud activiti-cloud-services-query-repo @@ -40,11 +45,26 @@ activiti-cloud-services-query-liquibase ${project.version} + + org.activiti.cloud + activiti-cloud-services-query-consumer + ${project.version} + org.activiti.cloud activiti-cloud-starter-query ${project.version} + + org.activiti.cloud + activiti-cloud-starter-query-rest + ${project.version} + + + org.activiti.cloud + activiti-cloud-starter-query-consumer + ${project.version} + org.activiti.cloud activiti-cloud-starter-query @@ -84,6 +104,11 @@ ${querydsl.version} jakarta + + io.github.classgraph + classgraph + ${classgraph.version} + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/pom.xml new file mode 100644 index 00000000000..88c29491d67 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/pom.xml @@ -0,0 +1,114 @@ + + 4.0.0 + + org.activiti.cloud + activiti-cloud-services-query + 8.7.0-SNAPSHOT + + activiti-cloud-services-query-consumer + Activiti Cloud Query :: Services :: Query Events Consumer + + + + org.springframework + spring-context + + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-autoconfigure + true + + + org.activiti.cloud + activiti-cloud-service-common-config + + + org.activiti.cloud + activiti-cloud-service-messaging-config + + + org.activiti.cloud + activiti-cloud-services-query-model + + + org.activiti.cloud + activiti-cloud-services-query-events + + + org.activiti.cloud + activiti-cloud-services-query-repo + + + org.apache.commons + commons-lang3 + + + org.springframework.cloud + spring-cloud-starter-stream-rabbit + test + + + org.springframework.boot + spring-boot-starter-data-jpa + test + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-generated-assertions-folder + generate-test-sources + + add-test-source + + + + ${generated-assertions-folder} + + + + + + + org.assertj + assertj-assertions-generator-maven-plugin + + + + generate-assertions + + + + + + org.activiti.cloud.services.query.model + + + true + + ${generated-assertions-package} + ${generated-assertions-folder} + true + false + false + false + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/conf/QueryConsumerAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/conf/QueryConsumerAutoConfiguration.java new file mode 100644 index 00000000000..b5a12a19faa --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/conf/QueryConsumerAutoConfiguration.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.conf; + +import java.util.List; +import java.util.function.Consumer; +import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; +import org.activiti.cloud.common.messaging.functional.FunctionBinding; +import org.activiti.cloud.services.query.app.QueryConsumerChannelHandler; +import org.activiti.cloud.services.query.app.QueryConsumerChannels; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +@AutoConfiguration +@Import(QueryConsumerChannelsConfiguration.class) +public class QueryConsumerAutoConfiguration { + + @FunctionBinding(input = QueryConsumerChannels.QUERY_CONSUMER) + @Bean + public Consumer>> queryConsumerFunction( + QueryConsumerChannelHandler queryConsumerChannelHandler + ) { + return queryConsumerChannelHandler::receive; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryConsumerChannelsConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/conf/QueryConsumerChannelsConfiguration.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryConsumerChannelsConfiguration.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/conf/QueryConsumerChannelsConfiguration.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannels.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannels.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannels.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannels.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..6a5afab6e20 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.activiti.cloud.conf.QueryConsumerAutoConfiguration diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/test/resources/logback-test.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e1f95399f50 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-consumer/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/pom.xml new file mode 100644 index 00000000000..68abec20ea2 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/pom.xml @@ -0,0 +1,146 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-services-query + 8.7.0-SNAPSHOT + + + activiti-cloud-services-query-events + Activiti Cloud Query :: Services :: Query Event Handlers + + + + org.springframework + spring-context + + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-autoconfigure + true + + + org.activiti.cloud + activiti-cloud-service-common-config + + + org.activiti.cloud + activiti-cloud-api-model-shared + + + org.activiti.cloud + activiti-cloud-api-process-model + + + org.activiti + activiti-api-task-model + + + org.activiti.cloud + activiti-cloud-api-task-model + + + org.activiti + activiti-api-model-shared + + + org.activiti + activiti-api-runtime-shared + + + org.activiti + activiti-api-process-model + + + org.activiti.cloud + activiti-cloud-api-task-model-impl + + + org.activiti.cloud + activiti-cloud-api-process-model-impl + + + org.activiti.cloud + activiti-cloud-services-query-model + + + org.activiti.cloud + activiti-cloud-services-query-repo + + + org.apache.commons + commons-lang3 + + + org.springframework.boot + spring-boot-starter-data-jpa + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.integration + spring-integration-core + test + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-generated-assertions-folder + generate-test-sources + + add-test-source + + + + ${generated-assertions-folder} + + + + + + + org.assertj + assertj-assertions-generator-maven-plugin + + + + generate-assertions + + + + + + org.activiti.cloud.services.query.model + + + true + + ${generated-assertions-package} + ${generated-assertions-folder} + true + false + false + false + + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannelHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannelHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannelHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/app/QueryConsumerChannelHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/EventHandlersAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/config/EventHandlersAutoConfiguration.java similarity index 95% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/EventHandlersAutoConfiguration.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/config/EventHandlersAutoConfiguration.java index 90440d57b75..83d6221058c 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/EventHandlersAutoConfiguration.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/config/EventHandlersAutoConfiguration.java @@ -13,16 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.activiti.cloud.conf; +package org.activiti.cloud.services.query.events.config; import jakarta.persistence.EntityManager; -import java.util.List; import java.util.Set; -import java.util.function.Consumer; -import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; -import org.activiti.cloud.common.messaging.functional.FunctionBinding; import org.activiti.cloud.services.query.app.QueryConsumerChannelHandler; -import org.activiti.cloud.services.query.app.QueryConsumerChannels; import org.activiti.cloud.services.query.app.repository.ApplicationRepository; import org.activiti.cloud.services.query.events.handlers.ApplicationDeployedEventHandler; import org.activiti.cloud.services.query.events.handlers.BPMNActivityCancelledEventHandler; @@ -74,10 +69,8 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; @AutoConfiguration -@Import(QueryConsumerChannelsConfiguration.class) public class EventHandlersAutoConfiguration { @Bean @@ -358,12 +351,4 @@ public ProcessCandidateStarterGroupRemovedEventHandler processCandidateStarterGr ) { return new ProcessCandidateStarterGroupRemovedEventHandler(entityManager); } - - @FunctionBinding(input = QueryConsumerChannels.QUERY_CONSUMER) - @Bean - public Consumer>> queryConsumerFunction( - QueryConsumerChannelHandler queryConsumerChannelHandler - ) { - return queryConsumerChannelHandler::receive; - } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCancelledEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCancelledEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCancelledEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCancelledEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCompletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCompletedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCompletedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityCompletedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityStartedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityStartedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityStartedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNActivityStartedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNSequenceFlowTakenEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNSequenceFlowTakenEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNSequenceFlowTakenEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BPMNSequenceFlowTakenEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseBPMNActivityEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseBPMNActivityEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseBPMNActivityEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseBPMNActivityEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseIntegrationEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseIntegrationEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseIntegrationEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/BaseIntegrationEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinder.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinder.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinder.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandler.java similarity index 95% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandler.java index c0641a2c9fe..d9b489dba59 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandler.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandler.java @@ -15,8 +15,6 @@ */ package org.activiti.cloud.services.query.events.handlers; -import static org.apache.commons.lang3.ObjectUtils.isNotEmpty; - import jakarta.persistence.EntityManager; import java.util.ArrayList; import java.util.Date; @@ -29,7 +27,7 @@ import org.activiti.cloud.api.process.model.events.CloudIntegrationErrorReceivedEvent; import org.activiti.cloud.services.query.model.IntegrationContextEntity; import org.activiti.cloud.services.query.model.ServiceTaskEntity; -import org.jetbrains.annotations.NotNull; +import org.apache.commons.lang3.ObjectUtils; public class IntegrationErrorReceivedEventHandler extends BaseIntegrationEventHandler implements QueryEventHandler { @@ -62,7 +60,6 @@ public void handle(CloudRuntimeEvent event) { }); } - @NotNull private List addFullErrorMessageAsFirstStackTraceElement( CloudIntegrationErrorReceivedEvent integrationEvent ) { @@ -72,9 +69,8 @@ private List addFullErrorMessageAsFirstStackTraceElement( return stackTraceElements; } - @NotNull private StackTraceElement getNewTopStackTraceElement(CloudIntegrationErrorReceivedEvent integrationEvent) { - if (isNotEmpty(integrationEvent.getStackTraceElements())) { + if (ObjectUtils.isNotEmpty(integrationEvent.getStackTraceElements())) { StackTraceElement firstElement = integrationEvent.getStackTraceElements().get(0); return new StackTraceElement( integrationEvent.getErrorMessage(), diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationResultReceivedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationResultReceivedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationResultReceivedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/IntegrationResultReceivedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandler.java new file mode 100644 index 00000000000..e1362892243 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandler.java @@ -0,0 +1,146 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.events.handlers; + +import jakarta.persistence.EntityManager; +import java.util.Optional; +import java.util.Set; +import org.activiti.api.process.model.ProcessInstance.ProcessInstanceStatus; +import org.activiti.api.process.model.events.ProcessRuntimeEvent; +import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; +import org.activiti.cloud.api.process.model.events.CloudProcessDeletedEvent; +import org.activiti.cloud.services.query.model.BPMNActivityEntity; +import org.activiti.cloud.services.query.model.BPMNSequenceFlowEntity; +import org.activiti.cloud.services.query.model.IntegrationContextEntity; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.QueryException; +import org.activiti.cloud.services.query.model.ServiceTaskEntity; +import org.activiti.cloud.services.query.model.TaskCandidateGroupEntity; +import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.model.TaskVariableEntity; + +public class ProcessDeletedEventHandler implements QueryEventHandler { + + protected final String INVALID_PROCESS_INSTANCE_STATE = + "Process Instance %s is not in a valid state: %s. " + + "Only process instances in status COMPLETED or CANCELLED can be deleted."; + + private Set ALLOWED_STATUS = Set.of( + ProcessInstanceStatus.CANCELLED, + ProcessInstanceStatus.COMPLETED + ); + + private final EntityManager entityManager; + + public ProcessDeletedEventHandler(EntityManager entityManager) { + this.entityManager = entityManager; + } + + @Override + public void handle(CloudRuntimeEvent event) { + CloudProcessDeletedEvent deletedEvent = (CloudProcessDeletedEvent) event; + + var eventProcessInstanceId = deletedEvent.getEntity().getId(); + + ProcessInstanceEntity processInstanceEntity = Optional + .ofNullable(entityManager.find(ProcessInstanceEntity.class, eventProcessInstanceId)) + .orElseThrow(() -> + new QueryException("Unable to find process instance with the given id: " + eventProcessInstanceId) + ); + + if (ALLOWED_STATUS.contains(processInstanceEntity.getStatus())) { + remove( + TaskCandidateUserEntity.class, + "taskId", + TaskEntity.class, + "id", + "processInstanceId", + eventProcessInstanceId + ); + + remove( + TaskCandidateGroupEntity.class, + "taskId", + TaskEntity.class, + "id", + "processInstanceId", + eventProcessInstanceId + ); + + remove(TaskVariableEntity.class, "processInstanceId", eventProcessInstanceId); + remove(TaskEntity.class, "processInstanceId", eventProcessInstanceId); + remove(ProcessVariableEntity.class, "processInstanceId", eventProcessInstanceId); + remove(IntegrationContextEntity.class, "processInstanceId", eventProcessInstanceId); + remove(ServiceTaskEntity.class, "processInstanceId", eventProcessInstanceId); + remove(BPMNActivityEntity.class, "processInstanceId", eventProcessInstanceId); + remove(BPMNSequenceFlowEntity.class, "processInstanceId", eventProcessInstanceId); + remove(ProcessInstanceEntity.class, "id", eventProcessInstanceId); + } else { + throw new IllegalStateException( + String.format( + INVALID_PROCESS_INSTANCE_STATE, + processInstanceEntity.getId(), + processInstanceEntity.getStatus().name() + ) + ); + } + } + + void remove(Class entityClass, String attributeName, Object attributeValue) { + var criteriaBuilder = entityManager.getCriteriaBuilder(); + + var delete = criteriaBuilder.createCriteriaDelete(entityClass); + var from = delete.from(entityClass); + + delete.where(criteriaBuilder.equal(from.get(attributeName), attributeValue)); + + entityManager.createQuery(delete).executeUpdate(); + } + + void remove( + Class entityClass, + String attributeName, + Class

parentClass, + String parentIdAttribute, + String parentAttributeName, + Object parentAttributeValue + ) { + var criteriaBuilder = entityManager.getCriteriaBuilder(); + + var parentQuery = criteriaBuilder.createQuery(Object.class); + var parentFrom = parentQuery.from(parentClass); + parentQuery.select(parentFrom.get(parentIdAttribute)); + parentQuery.where(criteriaBuilder.equal(parentFrom.get(parentAttributeName), parentAttributeValue)); + + var parentIds = entityManager.createQuery(parentQuery).getResultList(); + + if (!parentIds.isEmpty()) { + var delete = criteriaBuilder.createCriteriaDelete(entityClass); + var from = delete.from(entityClass); + + delete.where(from.get(attributeName).in(parentIds)); + + entityManager.createQuery(delete).executeUpdate(); + } + } + + @Override + public String getHandledEvent() { + return ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED.name(); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableCreatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableCreatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableCreatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableCreatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableDeletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableDeletedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableDeletedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableDeletedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdateEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdateEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdateEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdateEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdater.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdater.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdater.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableUpdater.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContext.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContext.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContext.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContext.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizer.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizer.java similarity index 71% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizer.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizer.java index 8361afc87cb..f4b9addab74 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizer.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizer.java @@ -18,13 +18,18 @@ import jakarta.persistence.AttributeNode; import jakarta.persistence.EntityGraph; import jakarta.persistence.EntityManager; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import org.activiti.api.model.shared.model.VariableInstance; +import org.activiti.api.task.model.Task; import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; import org.activiti.cloud.api.model.shared.events.CloudVariableEvent; import org.activiti.cloud.api.model.shared.impl.events.CloudVariableCreatedEventImpl; @@ -45,6 +50,7 @@ import org.activiti.cloud.api.process.model.impl.events.CloudProcessCandidateStarterUserRemovedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessCompletedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessCreatedEventImpl; +import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessStartedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessSuspendedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessUpdatedEventImpl; @@ -61,6 +67,7 @@ import org.activiti.cloud.api.task.model.impl.events.CloudTaskCreatedEventImpl; import org.activiti.cloud.api.task.model.impl.events.CloudTaskSuspendedEventImpl; import org.activiti.cloud.api.task.model.impl.events.CloudTaskUpdatedEventImpl; +import org.activiti.cloud.services.query.model.BPMNActivityEntity; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.hibernate.jpa.AvailableHints; import org.slf4j.Logger; @@ -108,7 +115,8 @@ public class QueryEventHandlerContextOptimizer { Map.entry(CloudProcessCandidateStarterUserAddedEventImpl.class, 17), Map.entry(CloudProcessCandidateStarterGroupAddedEventImpl.class, 17), Map.entry(CloudProcessCandidateStarterUserRemovedEventImpl.class, 18), - Map.entry(CloudProcessCandidateStarterGroupRemovedEventImpl.class, 18) + Map.entry(CloudProcessCandidateStarterGroupRemovedEventImpl.class, 18), + Map.entry(CloudProcessDeletedEventImpl.class, 19) ); private Comparator> byTimestamp = Comparator.comparingLong(CloudRuntimeEvent::getTimestamp); @@ -125,25 +133,51 @@ public QueryEventHandlerContextOptimizer(EntityManager entityManager) { resolveProcessInstanceId(events) .ifPresent(processInstanceId -> { LOGGER.debug("Building entity fetch graph for root process instance: {}", processInstanceId); - EntityGraph entityGraph = entityManager.createEntityGraph( - ProcessInstanceEntity.class - ); - - findRuntimeEvent(events, CloudVariableEvent.class) - .ifPresent(e -> entityGraph.addAttributeNodes(VARIABLES)); - findRuntimeEvent(events, CloudTaskRuntimeEvent.class) - .ifPresent(e -> entityGraph.addAttributeNodes(TASKS)); - findRuntimeEvent(events, CloudBPMNActivityEvent.class) - .ifPresent(e -> entityGraph.addAttributeNodes(ACTIVITIES, SERVICE_TASKS)); - - Optional - .ofNullable( - entityManager.find( - ProcessInstanceEntity.class, - processInstanceId, - Map.of(AvailableHints.HINT_SPEC_LOAD_GRAPH, entityGraph) - ) - ) + var entityGraph = entityManager.createEntityGraph(ProcessInstanceEntity.class); + + var criteriaBuilder = entityManager.getCriteriaBuilder(); + var criteriaQuery = criteriaBuilder.createQuery(ProcessInstanceEntity.class); + var fromProcessInstance = criteriaQuery.from(ProcessInstanceEntity.class); + var whereProcessInstance = criteriaBuilder.equal(fromProcessInstance.get("id"), processInstanceId); + + criteriaQuery.select(fromProcessInstance).where(whereProcessInstance); + + findRuntimeEvents(events, CloudVariableEvent.class, entity -> true, VariableInstance::getName) + .ifPresent(variableNames -> { + fetch(fromProcessInstance, entityGraph, VARIABLES, "name", variableNames); + }); + + findRuntimeEvents(events, CloudTaskRuntimeEvent.class, entity -> true, Task::getId) + .ifPresent(taskIds -> { + fetch(fromProcessInstance, entityGraph, TASKS, "id", taskIds); + }); + + findRuntimeEvents( + events, + CloudBPMNActivityEvent.class, + entity -> true, + BPMNActivityEntity.IdBuilderHelper::from + ) + .ifPresent(activityIds -> { + fetch(fromProcessInstance, entityGraph, ACTIVITIES, "id", activityIds); + }); + + findRuntimeEvents( + events, + CloudBPMNActivityEvent.class, + entity -> SERVICE_TASKS.equals(entity.getActivityType()), + BPMNActivityEntity.IdBuilderHelper::from + ) + .ifPresent(serviceTaskIds -> { + fetch(fromProcessInstance, entityGraph, SERVICE_TASKS, "id", serviceTaskIds); + }); + + entityManager + .createQuery(criteriaQuery) + .setHint(AvailableHints.HINT_SPEC_LOAD_GRAPH, entityGraph) + .getResultList() + .stream() + .findFirst() .ifPresent(rootProcessInstance -> { if (LOGGER.isDebugEnabled()) { LOGGER.debug( @@ -173,17 +207,36 @@ protected Optional resolveProcessInstanceId(List return events.stream().filter(runtimeEventClass::isInstance).findFirst(); } - protected Optional findRuntimeEvent( + protected Optional> findRuntimeEvents( List> events, Class> runtimeEventClass, - Predicate predicate + Predicate predicate, + Function mapper + ) { + return Optional + .of( + events + .stream() + .filter(runtimeEventClass::isInstance) + .map(runtimeEventClass::cast) + .map(CloudRuntimeEvent::getEntity) + .filter(predicate) + .map(mapper) + .distinct() + .toList() + ) + .filter(Predicate.not(List::isEmpty)); + } + + protected void fetch( + Root from, + EntityGraph entityGraph, + String association, + String attribute, + List ids ) { - return events - .stream() - .filter(runtimeEventClass::isInstance) - .map(runtimeEventClass::cast) - .map(CloudRuntimeEvent::getEntity) - .filter(predicate) - .findFirst(); + entityGraph.addAttributeNodes(association); + var join = (Join) from.fetch(association); + join.on(join.get(attribute).in(ids)); } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskActivatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskActivatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskActivatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskActivatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskAssignedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskAssignedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskAssignedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskAssignedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCancelledEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCancelledEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCancelledEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCancelledEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupAddedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupAddedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupAddedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupAddedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupRemovedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupRemovedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupRemovedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateGroupRemovedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserAddedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserAddedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserAddedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserAddedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserRemovedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserRemovedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserRemovedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCandidateUserRemovedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCompletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCompletedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCompletedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCompletedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCreatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCreatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCreatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskCreatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskSuspendedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskSuspendedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskSuspendedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskSuspendedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskUpdatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskUpdatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskUpdatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskUpdatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableCreatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableCreatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableCreatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableCreatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableDeletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableDeletedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableDeletedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableDeletedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdater.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdater.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdater.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/TaskVariableUpdater.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableCreatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableCreatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableCreatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableCreatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableDeletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableDeletedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableDeletedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableDeletedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableUpdatedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableUpdatedEventHandler.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableUpdatedEventHandler.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/java/org/activiti/cloud/services/query/events/handlers/VariableUpdatedEventHandler.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..3fdae482fb2 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.activiti.cloud.services.query.events.config.EventHandlersAutoConfiguration diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinderTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinderTest.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinderTest.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/EntityManagerFinderTest.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandlerTest.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandlerTest.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupAddedEventHandlerTest.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/QueryConsumerChannelHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryConsumerChannelHandlerTest.java similarity index 92% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/QueryConsumerChannelHandlerTest.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryConsumerChannelHandlerTest.java index 926512270b1..a2bfc83665a 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/QueryConsumerChannelHandlerTest.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryConsumerChannelHandlerTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.activiti.cloud.services.query; +package org.activiti.cloud.services.query.events.handlers; import static java.util.Arrays.asList; import static org.mockito.Mockito.verify; @@ -25,8 +25,6 @@ import org.activiti.cloud.api.process.model.impl.events.CloudProcessCreatedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessStartedEventImpl; import org.activiti.cloud.services.query.app.QueryConsumerChannelHandler; -import org.activiti.cloud.services.query.events.handlers.QueryEventHandlerContext; -import org.activiti.cloud.services.query.events.handlers.QueryEventHandlerContextOptimizer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskBuilder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskBuilder.java new file mode 100644 index 00000000000..3ca93a312f1 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskBuilder.java @@ -0,0 +1,105 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.events.handlers; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Date; +import java.util.List; +import org.activiti.cloud.services.query.model.TaskEntity; + +public class TaskBuilder { + + private TaskEntity taskEntity; + + private TaskBuilder() { + this.taskEntity = mock(TaskEntity.class); + } + + public static TaskBuilder aTask() { + return new TaskBuilder(); + } + + public TaskBuilder withId(String taskId) { + when(taskEntity.getId()).thenReturn(taskId); + return this; + } + + public TaskBuilder withName(String name) { + when(taskEntity.getName()).thenReturn(name); + return this; + } + + public TaskBuilder withDescription(String description) { + when(taskEntity.getDescription()).thenReturn(description); + return this; + } + + public TaskBuilder withPriority(Integer priority) { + when(taskEntity.getPriority()).thenReturn(priority); + return this; + } + + public TaskBuilder withDueDate(Date dueDate) { + when(taskEntity.getDueDate()).thenReturn(dueDate); + return this; + } + + public TaskBuilder withFormKey(String formKey) { + when(taskEntity.getFormKey()).thenReturn(formKey); + return this; + } + + public TaskBuilder withParentTaskId(String parentTaskId) { + when(taskEntity.getParentTaskId()).thenReturn(parentTaskId); + return this; + } + + public TaskBuilder withAssignee(String assignee) { + when(taskEntity.getAssignee()).thenReturn(assignee); + return this; + } + + public TaskBuilder withCreatedDate(Date createdDate) { + when(taskEntity.getCreatedDate()).thenReturn(createdDate); + return this; + } + + public TaskBuilder withCompletedDate(Date completedDate) { + when(taskEntity.getCompletedDate()).thenReturn(completedDate); + return this; + } + + public TaskBuilder withCandidateUsers(List candidateUsers) { + when(taskEntity.getCandidateUsers()).thenReturn(candidateUsers); + return this; + } + + public TaskBuilder withCandidateGroups(List candidateGroups) { + when(taskEntity.getCandidateGroups()).thenReturn(candidateGroups); + return this; + } + + public TaskBuilder withOwner(String owner) { + when(taskEntity.getOwner()).thenReturn(owner); + return this; + } + + public TaskEntity build() { + return taskEntity; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityCreatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityCreatedEventHandlerTest.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityCreatedEventHandlerTest.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityCreatedEventHandlerTest.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdaterTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdaterTest.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdaterTest.java rename to activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdaterTest.java diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/resources/logback-test.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e1f95399f50 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-events/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/pom.xml index 212c3004bc8..5ec89bd62ad 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/pom.xml @@ -3,7 +3,7 @@ org.activiti.cloud activiti-cloud-services-query - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-query-liquibase diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/23-alter.oracle.schema.8.6.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/23-alter.oracle.schema.8.6.0.sql new file mode 100644 index 00000000000..0b2e7065170 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/23-alter.oracle.schema.8.6.0.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 INDEX CONCURRENTLY IF NOT EXISTS task_process_variable_task_id_idx ON task_process_variable (task_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS task_process_variable_process_variable_id_idx ON task_process_variable (process_variable_id); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/23-alter.pg.schema.8.6.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/23-alter.pg.schema.8.6.0.sql new file mode 100644 index 00000000000..0b2e7065170 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/23-alter.pg.schema.8.6.0.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 INDEX CONCURRENTLY IF NOT EXISTS task_process_variable_task_id_idx ON task_process_variable (task_id); +CREATE INDEX CONCURRENTLY IF NOT EXISTS task_process_variable_process_variable_id_idx ON task_process_variable (process_variable_id); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/24-alter.oracle.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/24-alter.oracle.schema.8.7.0.sql new file mode 100644 index 00000000000..d10f663f078 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/24-alter.oracle.schema.8.7.0.sql @@ -0,0 +1,20 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +ALTER TABLE process_variable ADD (temp_value JSON); +UPDATE process_variable SET temp_value = value WHERE true; +ALTER TABLE process_variable DROP COLUMN value; +ALTER TABLE process_variable RENAME COLUMN temp_value TO value; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/24-alter.pg.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/24-alter.pg.schema.8.7.0.sql new file mode 100644 index 00000000000..08adf2c4755 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/24-alter.pg.schema.8.7.0.sql @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +ALTER TABLE process_variable +ALTER COLUMN "value" TYPE jsonb USING "value"::jsonb; + +ALTER TABLE task_variable +ALTER COLUMN "value" TYPE jsonb USING "value"::jsonb; + +CREATE INDEX process_variable_value_idx ON process_variable USING GIN ((value -> 'value') jsonb_path_ops); +CREATE INDEX process_definition_key_name_value_idx ON process_variable (process_definition_key,name); + +CREATE INDEX task_variable_value_idx ON task_variable USING GIN ((value -> 'value') jsonb_path_ops); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/25-alter.oracle.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/25-alter.oracle.schema.8.7.0.sql new file mode 100644 index 00000000000..d37aa6b28fb --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/25-alter.oracle.schema.8.7.0.sql @@ -0,0 +1,19 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 index if not exists idx_task_assignee on task(assignee); +create index if not exists idx_task_owner on task(owner); +create index if not exists idx_process_instance_initiator on process_instance(initiator); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/25-alter.pg.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/25-alter.pg.schema.8.7.0.sql new file mode 100644 index 00000000000..d37aa6b28fb --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/25-alter.pg.schema.8.7.0.sql @@ -0,0 +1,19 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 index if not exists idx_task_assignee on task(assignee); +create index if not exists idx_task_owner on task(owner); +create index if not exists idx_process_instance_initiator on process_instance(initiator); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/26-alter.oracle.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/26-alter.oracle.schema.8.7.0.sql new file mode 100644 index 00000000000..97bf0ed584e --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/26-alter.oracle.schema.8.7.0.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +ALTER TABLE process_definition + MODIFY description varchar(4000); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/26-alter.pg.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/26-alter.pg.schema.8.7.0.sql new file mode 100644 index 00000000000..e9d844d1467 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/26-alter.pg.schema.8.7.0.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +ALTER TABLE process_definition + ALTER COLUMN description TYPE varchar(4000); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/27-alter.oracle.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/27-alter.oracle.schema.8.7.0.sql new file mode 100644 index 00000000000..0c6a16040ea --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/27-alter.oracle.schema.8.7.0.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 INDEX idx_task_process_var_taskId_processVarId ON task_process_variable (task_id, process_variable_id); +CREATE INDEX idx_task_createdDate ON task (created_date); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/27-alter.pg.schema.8.7.0.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/27-alter.pg.schema.8.7.0.sql new file mode 100644 index 00000000000..0c6a16040ea --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/27-alter.pg.schema.8.7.0.sql @@ -0,0 +1,18 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 INDEX idx_task_process_var_taskId_processVarId ON task_process_variable (task_id, process_variable_id); +CREATE INDEX idx_task_createdDate ON task (created_date); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/h2.schema.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/h2.schema.sql index dee80ebb289..11f3c072876 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/h2.schema.sql +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/h2.schema.sql @@ -60,7 +60,7 @@ create table process_definition service_name varchar(255), service_type varchar(255), service_version varchar(255), - description varchar(255), + description varchar(4000), form_key varchar(255), process_definition_key varchar(255), name varchar(255), @@ -118,7 +118,7 @@ create table process_variable name varchar(255), process_instance_id varchar(255), type varchar(255), - "value" text, + "value" json, variable_definition_id varchar(64), process_definition_key varchar(255), primary key (id) @@ -191,7 +191,7 @@ create table task_variable name varchar(255), process_instance_id varchar(255), type varchar(255), - "value" text, + "value" json, task_id varchar(255), primary key (id) ); @@ -309,3 +309,8 @@ alter table task_process_variable add constraint fk_process_variable_id foreign key (process_variable_id) references process_variable; alter table task_process_variable add constraint uk_task_process_var unique (task_id, process_variable_id); +create index idx_task_assignee on task(assignee); +create index idx_task_owner on task(owner); +create index idx_process_instance_initiator on process_instance(initiator); +CREATE INDEX idx_task_process_var_taskId_processVarId ON task_process_variable (task_id, process_variable_id); +CREATE INDEX idx_task_createdDate ON task (created_date); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/oracle.schema.sql b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/oracle.schema.sql index 4ee9b0e5614..14186edc856 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/oracle.schema.sql +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/changelog/oracle.schema.sql @@ -109,7 +109,7 @@ create table process_variable name varchar(255), process_instance_id varchar(255), type varchar(255), - value CLOB, + value json, primary key (id) ); create table task @@ -178,7 +178,7 @@ create table task_variable name varchar(255), process_instance_id varchar(255), type varchar(255), - value CLOB, + value json, task_id varchar(255), primary key (id) ); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/master.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/master.xml index 7e553c35825..7836cf474fa 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/master.xml +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-liquibase/src/main/resources/config/query/liquibase/master.xml @@ -462,4 +462,110 @@ stripComments="true"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/pom.xml index 65283826aa5..fe49dd00954 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-query - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-query-model Activiti Cloud Query :: Services :: Query Model @@ -108,16 +108,16 @@ json-unit-fluent test - - io.swagger.core.v3 - swagger-annotations-jakarta - 2.2.9 - com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.16.1 + + org.hibernate + hibernate-jpamodelgen + 6.5.2.Final + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/AbstractVariableEntity.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/AbstractVariableEntity.java index b326ec0b4f6..f1f5bddbd8a 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/AbstractVariableEntity.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/AbstractVariableEntity.java @@ -30,6 +30,8 @@ import java.util.Date; import java.util.Objects; import org.activiti.cloud.api.model.shared.CloudVariableInstance; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; import org.springframework.format.annotation.DateTimeFormat; @MappedSuperclass @@ -50,7 +52,8 @@ public abstract class AbstractVariableEntity extends ActivitiEntityMetadata impl private String executionId; @Convert(converter = VariableValueJsonConverter.class) - @Column(name = "`value`", columnDefinition = "text") + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "`value`", columnDefinition = "jsonb") @Basic(fetch = FetchType.LAZY) private VariableValue value; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessVariableKey.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessVariableKey.java new file mode 100644 index 00000000000..541d8b17448 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/ProcessVariableKey.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.model; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonSetter; + +public record ProcessVariableKey(String processDefinitionKey, String variableName) { + @JsonSetter + public static ProcessVariableKey fromString(String processVariableKey) { + String[] parts = processVariableKey.split("/"); + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid process variable key: " + processVariableKey); + } + return new ProcessVariableKey(parts[0], parts[1]); + } + + @JsonGetter + public static String toString(ProcessVariableKey processVariableKey) { + return processVariableKey.processDefinitionKey() + "/" + processVariableKey.variableName(); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/TaskEntity.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/TaskEntity.java index 8c71f3c4efb..25f1169f518 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/TaskEntity.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-model/src/main/java/org/activiti/cloud/services/query/model/TaskEntity.java @@ -55,7 +55,6 @@ import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; -import org.hibernate.annotations.Filter; import org.springframework.format.annotation.DateTimeFormat; @Entity(name = "Task") @@ -229,7 +228,6 @@ public class TaskEntity extends ActivitiEntityMetadata implements QueryCloudTask private Set variables = new LinkedHashSet<>(); @JsonView(JsonViews.ProcessVariables.class) - @Filter(name = "variablesFilter") @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) @JoinTable( name = "task_process_variable", diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/pom.xml index fb5fa49ddc3..564c5d6d0c9 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-query - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-query-repo Activiti Cloud Query :: Services :: Query Repo @@ -22,10 +22,6 @@ org.springframework spring-context - - org.springframework.data - spring-data-rest-core - com.querydsl querydsl-apt diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ApplicationRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ApplicationRepository.java index f3e478423f4..38681d1582e 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ApplicationRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ApplicationRepository.java @@ -25,9 +25,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface ApplicationRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNActivityRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNActivityRepository.java index 9f6f62bd010..53cc1c505c9 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNActivityRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNActivityRepository.java @@ -27,9 +27,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface BPMNActivityRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNSequenceFlowRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNSequenceFlowRepository.java index e86b1bd3c44..6f3d7c65238 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNSequenceFlowRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/BPMNSequenceFlowRepository.java @@ -26,9 +26,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface BPMNSequenceFlowRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepository.java index 27ed68bed1e..f044260663d 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepository.java @@ -16,7 +16,6 @@ package org.activiti.cloud.services.query.app.repository; import com.querydsl.core.types.Predicate; -import java.util.List; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.query.model.VariableValue; import org.springframework.data.domain.Page; @@ -30,8 +29,6 @@ Page findByVariableNameAndValue( Pageable pageable ); - Page findWithProcessVariables(List variableKeys, Predicate predicate, Pageable pageable); - Iterable findInProcessInstanceScope(Predicate predicate); Page findInProcessInstanceScope(Predicate predicate, Pageable pageable); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepositoryImpl.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepositoryImpl.java index fc1be660619..78827d081f2 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepositoryImpl.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/CustomizedTaskRepositoryImpl.java @@ -16,7 +16,6 @@ package org.activiti.cloud.services.query.app.repository; import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQuery; @@ -24,7 +23,6 @@ import jakarta.persistence.EntityManager; import java.util.List; import org.activiti.cloud.services.query.model.QProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QProcessVariableEntity; import org.activiti.cloud.services.query.model.QTaskEntity; import org.activiti.cloud.services.query.model.QTaskVariableEntity; import org.activiti.cloud.services.query.model.TaskEntity; @@ -92,54 +90,6 @@ public Page findByVariableNameAndValue( ); } - @Override - public Page findWithProcessVariables( - List variableKeys, - Predicate predicate, - Pageable pageable - ) { - Assert.notNull(variableKeys, "keys must not be null!"); - Assert.notNull(predicate, "Predicate must not be null!"); - Assert.notNull(pageable, "Pageable must not be null!"); - - EntityManager entityManager = getEntityManager(); - Querydsl querydsl = getQuerydsl(); - JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager); - - QTaskEntity taskEntity = QTaskEntity.taskEntity; - QProcessVariableEntity processVariableEntity = QProcessVariableEntity.processVariableEntity; - - JPAQuery taskIdsQuery = queryFactory.query().select(taskEntity.id).from(taskEntity).where(predicate); - - long totalElements = taskIdsQuery.fetchCount(); - - List taskIds = querydsl.applyPagination(pageable, taskIdsQuery).fetch(); - - BooleanExpression processVariableFilter = processVariableEntity.processDefinitionKey - .concat("/") - .concat(processVariableEntity.name) - .in(variableKeys); - - JPQLQuery tasksQuery = queryFactory - .query() - .select(taskEntity) - .from(taskEntity) - .where(taskEntity.id.in(taskIds)) - .leftJoin(taskEntity.processVariables, processVariableEntity) - .where(processVariableEntity.isNull().or(processVariableFilter)) - .fetchJoin() - .leftJoin(taskEntity.taskCandidateGroups) - .fetchJoin() - .leftJoin(taskEntity.taskCandidateUsers) - .fetchJoin(); - - return PageableExecutionUtils.getPage( - querydsl.applySorting(pageable.getSort(), tasksQuery).fetch(), - pageable, - () -> totalElements - ); - } - @Override public Iterable findInProcessInstanceScope(Predicate predicate) { QTaskEntity taskEntity = QTaskEntity.taskEntity; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/EntityFinder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/EntityFinder.java index ba56c90665e..2bb56fc464d 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/EntityFinder.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/EntityFinder.java @@ -16,6 +16,7 @@ package org.activiti.cloud.services.query.app.repository; import com.querydsl.core.types.Predicate; +import jakarta.persistence.EntityNotFoundException; import java.util.Optional; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.repository.CrudRepository; @@ -28,7 +29,7 @@ public T findById(CrudRepository repository, ID id, String notFou } private T getEntity(Optional result, String notFoundMessage) { - return result.orElseThrow(() -> new IllegalStateException(notFoundMessage)); + return result.orElseThrow(() -> new EntityNotFoundException(notFoundMessage)); } public T findOne(QuerydslPredicateExecutor predicateExecutor, Predicate predicate, String notFoundMessage) { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/IntegrationContextRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/IntegrationContextRepository.java index 2c8f3984423..d606ee8de41 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/IntegrationContextRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/IntegrationContextRepository.java @@ -25,9 +25,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface IntegrationContextRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessDefinitionRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessDefinitionRepository.java index efb05cccb11..1540c129497 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessDefinitionRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessDefinitionRepository.java @@ -25,9 +25,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface ProcessDefinitionRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java index fb77cd47e6d..919e38fd68e 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessInstanceRepository.java @@ -25,17 +25,17 @@ import org.activiti.cloud.services.query.model.QProcessInstanceEntity; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface ProcessInstanceRepository extends PagingAndSortingRepository, + JpaSpecificationExecutor, QuerydslPredicateExecutor, QuerydslBinderCustomizer, CrudRepository { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessModelRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessModelRepository.java index 03f4094ce31..39d237558ff 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessModelRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ProcessModelRepository.java @@ -25,9 +25,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface ProcessModelRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ServiceTaskRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ServiceTaskRepository.java index c839a9bfe07..de4b2664988 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ServiceTaskRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/ServiceTaskRepository.java @@ -27,9 +27,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface ServiceTaskRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateGroupRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateGroupRepository.java index dd2033dc7e5..6c783ad280f 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateGroupRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateGroupRepository.java @@ -26,9 +26,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface TaskCandidateGroupRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateUserRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateUserRepository.java index 3485615aec7..51e31b6a467 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateUserRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskCandidateUserRepository.java @@ -26,9 +26,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface TaskCandidateUserRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskRepository.java index 8aa33cc9dd2..547604f65d8 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskRepository.java @@ -21,17 +21,17 @@ import java.util.Arrays; import org.activiti.cloud.services.query.model.QTaskEntity; import org.activiti.cloud.services.query.model.TaskEntity; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface TaskRepository extends PagingAndSortingRepository, + JpaSpecificationExecutor, QuerydslPredicateExecutor, QuerydslBinderCustomizer, CustomizedTaskRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskVariableRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskVariableRepository.java index ecbfc212693..6f81a8bb3b1 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskVariableRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/TaskVariableRepository.java @@ -25,9 +25,7 @@ import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface TaskVariableRepository extends PagingAndSortingRepository, diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/VariableRepository.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/VariableRepository.java index 3760693665c..142b3612aa9 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/VariableRepository.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/main/java/org/activiti/cloud/services/query/app/repository/VariableRepository.java @@ -20,17 +20,17 @@ import com.querydsl.core.types.dsl.StringPath; import org.activiti.cloud.services.query.model.ProcessVariableEntity; import org.activiti.cloud.services.query.model.QProcessVariableEntity; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; import org.springframework.data.querydsl.binding.QuerydslBindings; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -@RepositoryRestResource(exported = false) public interface VariableRepository extends PagingAndSortingRepository, + JpaSpecificationExecutor, QuerydslPredicateExecutor, QuerydslBinderCustomizer, CrudRepository { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/EntityFinderTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/EntityFinderTest.java index 073ea145470..aa9a51568bc 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/EntityFinderTest.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-repo/src/test/java/org/activiti/cloud/services/query/app/repository/EntityFinderTest.java @@ -18,9 +18,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; import com.querydsl.core.types.Predicate; +import jakarta.persistence.EntityNotFoundException; import java.util.Optional; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.junit.jupiter.api.Test; @@ -64,7 +65,7 @@ public void findByIdShouldThrowExceptionWhenNotPresent() throws Exception { //then //when - assertThatExceptionOfType(IllegalStateException.class) + assertThatExceptionOfType(EntityNotFoundException.class) .isThrownBy(() -> entityFinder.findById(repository, processInstanceId, "Error")) .withMessageContaining("Error"); } @@ -91,7 +92,7 @@ public void findOneShouldThrowExceptionWhenNotPresent() throws Exception { //then //when - assertThatExceptionOfType(IllegalStateException.class) + assertThatExceptionOfType(EntityNotFoundException.class) .isThrownBy(() -> entityFinder.findOne(repository, predicate, "Error")) .withMessageContaining("Error"); } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/pom.xml index 2c94886ff1c..3f02e2caa60 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/pom.xml @@ -4,7 +4,7 @@ org.activiti.cloud activiti-cloud-services-query - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT 4.0.0 activiti-cloud-services-query-rest @@ -14,6 +14,10 @@ jakarta.servlet jakarta.servlet-api + + jakarta.validation + jakarta.validation-api + org.activiti activiti-image-generator @@ -96,10 +100,6 @@ org.activiti.cloud activiti-cloud-api-process-model-impl - - org.activiti.cloud - activiti-cloud-service-messaging-config - org.springframework spring-core @@ -161,10 +161,6 @@ spring-boot-autoconfigure true - - org.springframework - spring-messaging - org.springframework spring-web @@ -173,11 +169,6 @@ org.springframework.hateoas spring-hateoas - - org.springframework.cloud - spring-cloud-stream - - io.swagger.core.v3 swagger-annotations-jakarta @@ -195,11 +186,6 @@ spring-boot-starter-web test - - org.springframework.cloud - spring-cloud-starter-stream-rabbit - test - org.springframework.boot spring-boot-starter-data-jpa @@ -240,7 +226,36 @@ activiti-cloud-services-query-liquibase test - + + org.testcontainers + junit-jupiter + test + + + org.springframework.boot + spring-boot-testcontainers + test + + + org.testcontainers + postgresql + test + + + org.postgresql + postgresql + test + + + org.springframework.boot + spring-boot-starter-hateoas + test + + + io.rest-assured + spring-mock-mvc + test + diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestControllersAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestControllersAutoConfiguration.java index 01ee9eab1b1..63ca8998366 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestControllersAutoConfiguration.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestControllersAutoConfiguration.java @@ -46,6 +46,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.rest.core.config.RepositoryRestConfiguration; +import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer; +import org.springframework.web.servlet.config.annotation.CorsRegistry; @AutoConfiguration @Import( @@ -76,6 +80,7 @@ ApplicationAdminController.class, } ) +@PropertySource("classpath:query-rest.properties") public class QueryRestControllersAutoConfiguration { @Bean @@ -91,4 +96,15 @@ public ProcessDiagramGeneratorWrapper processDiagramGeneratorWrapper( ) { return new ProcessDiagramGeneratorWrapper(processDiagramGenerator); } + + @Bean + @ConditionalOnMissingBean + RepositoryRestConfigurer dataRestRepositoryRestConfigurer() { + return new RepositoryRestConfigurer() { + @Override + public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) { + config.disableDefaultExposure(); + } + }; + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java index 7f6ceeedb9c..bf38a00ddaa 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/conf/QueryRestWebMvcAutoConfiguration.java @@ -20,9 +20,12 @@ import org.activiti.cloud.services.query.app.repository.EntityFinder; import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.query.rest.ProcessInstanceAdminService; +import org.activiti.cloud.services.query.rest.ProcessInstanceSearchService; import org.activiti.cloud.services.query.rest.ProcessInstanceService; +import org.activiti.cloud.services.query.rest.ProcessVariableService; import org.activiti.cloud.services.query.rest.QueryLinkRelationProvider; import org.activiti.cloud.services.query.rest.TaskControllerHelper; import org.activiti.cloud.services.query.rest.TaskPermissionsHelper; @@ -199,16 +202,20 @@ public ProcessDefinitionRestrictionService processDefinitionRestrictionService( @ConditionalOnMissingBean public TaskControllerHelper taskControllerHelper( TaskRepository taskRepository, + ProcessVariableService processVariableService, AlfrescoPagedModelAssembler pagedCollectionModelAssembler, TaskRepresentationModelAssembler taskRepresentationModelAssembler, - TaskLookupRestrictionService taskLookupRestrictionService + TaskLookupRestrictionService taskLookupRestrictionService, + SecurityManager securityManager ) { return new TaskControllerHelper( taskRepository, + processVariableService, pagedCollectionModelAssembler, new QueryDslPredicateAggregator(), taskRepresentationModelAssembler, - taskLookupRestrictionService + taskLookupRestrictionService, + securityManager ); } @@ -227,11 +234,28 @@ public TaskPermissionsHelper taskPermissionsHelper( return new TaskPermissionsHelper(securityManager, taskControllerHelper); } + @Bean + @ConditionalOnMissingBean + public ProcessVariableService processVariableService(VariableRepository variableRepository) { + return new ProcessVariableService(variableRepository); + } + + @Bean + @ConditionalOnMissingBean + public ProcessInstanceSearchService processInstanceSearchService( + ProcessInstanceRepository processInstanceRepository, + ProcessVariableService processVariableService, + SecurityManager securityManager + ) { + return new ProcessInstanceSearchService(processInstanceRepository, processVariableService, securityManager); + } + @Bean @ConditionalOnMissingBean public ProcessInstanceService processInstanceService( ProcessInstanceRepository processInstanceRepository, TaskRepository taskRepository, + ProcessInstanceSearchService processInstanceSearchService, ProcessInstanceRestrictionService processInstanceRestrictionService, SecurityPoliciesManager securityPoliciesApplicationService, SecurityManager securityManager, @@ -240,6 +264,7 @@ public ProcessInstanceService processInstanceService( return new ProcessInstanceService( processInstanceRepository, taskRepository, + processInstanceSearchService, processInstanceRestrictionService, securityPoliciesApplicationService, securityManager, @@ -251,10 +276,12 @@ public ProcessInstanceService processInstanceService( @ConditionalOnMissingBean public ProcessInstanceAdminService processInstanceAdminService( ProcessInstanceRepository processInstanceRepository, + ProcessInstanceSearchService processInstanceSearchService, EntityFinder entityFinder ) { return new ProcessInstanceAdminService( processInstanceRepository, + processInstanceSearchService, entityFinder, new QueryDslPredicateAggregator() ); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/CustomPostgreSQLDialect.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/CustomPostgreSQLDialect.java new file mode 100644 index 00000000000..d08e475b130 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/CustomPostgreSQLDialect.java @@ -0,0 +1,464 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.dialect; + +import java.util.Map; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.hibernate.boot.model.FunctionContributions; +import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.query.sqm.function.SqmFunctionRegistry; +import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.descriptor.java.StringJavaType; + +/** + * Custom PostgreSQL dialect to add custom JSONB functions that abstract the PostgreSQL JSON path operators: + * All functions accept exactly two arguments: + * 1. A JSONB column field or a SQL path to a JSONB field. + * 2. A value to compare with the extracted field "value" from the JSONB field. + */ +public class CustomPostgreSQLDialect extends PostgreSQLDialect { + + /** + * Extracts the "value" field from a JSONB column. + */ + public static final String EXTRACT_JSON_RAW_VALUE = "jsonb_value_extract"; + + /** + * Extracts the "value" field from a JSONB column and casts it to STRING. + */ + public static final String EXTRACT_JSON_STRING_VALUE = "jsonb_string_value_extract"; + + /** + * Extracts the "value" field from a JSONB column and casts it to NUMERIC. + */ + public static final String EXTRACT_JSON_NUMERIC_VALUE = "jsonb_numeric_value_extract"; + + /** + * Extracts the "value" field from a JSONB column and casts it to DATE. + */ + public static final String EXTRACT_JSON_DATE_VALUE = "jsonb_date_value_extract"; + + /** + * Extracts the "value" field from a JSONB column and casts it to TIMESTAMPTZ. + */ + public static final String EXTRACT_JSON_DATETIME_VALUE = "jsonb_datetime_value_extract"; + + /** + * Extracts the "value" field from a JSONB column and casts it to BOOLEAN. + */ + public static final String EXTRACT_JSON_BOOLEAN_VALUE = "jsonb_boolean_value_extract"; + + /** + * Extracts the "value" field from a JSONB column and compares it with the given value, returning true if they are equal. + * It works with strings and booleans. + */ + public static final String JSON_VALUE_EQUALS = "jsonb_value_eq"; + + /** + * Extracts the "value" field from a JSONB column, casts it to NUMERIC and compares it with the given value cast to NUMERIC, + * returning true if they are equal. + */ + public static final String JSON_VALUE_NUMERIC_EQUALS = "jsonb_numeric_eq"; + + /** + * Extracts the "value" field from a JSONB column, casts it to NUMERIC and compares it with the given value cast to NUMERIC, + * returning true if the extracted value is greater than the given value. + */ + public static final String JSON_VALUE_NUMERIC_GREATER_THAN = "jsonb_numeric_gt"; + + /** + * Extracts the "value" field from a JSONB column, casts it to NUMERIC and compares it with the given value cast to NUMERIC, + * returning true if the extracted value is greater than or equal to the given value. + */ + public static final String JSON_VALUE_NUMERIC_GREATER_THAN_EQUAL = "jsonb_numeric_gte"; + + /** + * Extracts the "value" field from a JSONB column, casts it to NUMERIC and compares it with the given value cast to NUMERIC, + * returning true if the extracted value is less than the given value. + */ + public static final String JSON_VALUE_NUMERIC_LESS_THAN = "jsonb_numeric_lt"; + + /** + * Extracts the "value" field from a JSONB column, casts it to NUMERIC and compares it with the given value cast to NUMERIC, + * returning true if the extracted value is less than or equal to the given value. + */ + public static final String JSON_VALUE_NUMERIC_LESS_THAN_EQUAL = "jsonb_numeric_lte"; + + /** + * Extracts the "value" field from a JSONB column and compares it with the given value using a case-sensitive regex pattern, + * returning true if the extracted value matches the pattern. The "value" field must contain a string. + */ + public static final String JSON_VALUE_LIKE_CASE_SENSITIVE = "jsonb_value_like_cs"; + + /** + * Extracts the "value" field from a JSONB column and compares it with the given value using a case-insensitive regex pattern, + * returning true if the extracted value matches the pattern. The "value" field must contain a string. + */ + public static final String JSON_VALUE_LIKE_CASE_INSENSITIVE = "jsonb_value_like_ci"; + + /** + * Extracts the "value" field from a JSONB column, casts it to DATE and compares it with the given value cast to DATE, + * returning true if they are equal. + */ + public static final String JSON_VALUE_DATE_EQUALS = "jsonb_date_eq"; + + /** + * Extracts the "value" field from a JSONB column, casts it to DATE and compares it with the given value cast to DATE, + * returning true if the extracted value is greater than the given value. + */ + public static final String JSON_VALUE_DATE_GREATER_THAN = "jsonb_date_gt"; + + /** + * Extracts the "value" field from a JSONB column, casts it to DATE and compares it with the given value cast to DATE, + * returning true if the extracted value is greater than or equal to the given value. + */ + public static final String JSON_VALUE_DATE_GREATER_THAN_EQUAL = "jsonb_date_gte"; + + /** + * Extracts the "value" field from a JSONB column, casts it to DATE and compares it with the given value cast to DATE, + * returning true if the extracted value is less than the given value. + */ + public static final String JSON_VALUE_DATE_LESS_THAN = "jsonb_date_lt"; + + /** + * Extracts the "value" field from a JSONB column, casts it to DATE and compares it with the given value cast to DATE, + * returning true if the extracted value is less than or equal to the given value. + */ + public static final String JSON_VALUE_DATE_LESS_THAN_EQUAL = "jsonb_date_lte"; + + /** + * Extracts the "value" field from a JSONB column, casts it to TIMESTAMPTZ and compares it with the given value cast to TIMESTAMPTZ, + * returning true if they are equal. + */ + public static final String JSON_VALUE_DATETIME_EQUALS = "jsonb_datetime_eq"; + + /** + * Extracts the "value" field from a JSONB column, casts it to TIMESTAMPTZ and compares it with the given value cast to TIMESTAMPTZ, + * returning true if the extracted value is greater than the given value. + */ + public static final String JSON_VALUE_DATETIME_GREATER_THAN = "jsonb_datetime_gt"; + + /** + * Extracts the "value" field from a JSONB column, casts it to TIMESTAMPTZ and compares it with the given value cast to TIMESTAMPTZ, + * returning true if the extracted value is greater than or equal to the given value. + */ + public static final String JSON_VALUE_DATETIME_GREATER_THAN_EQUAL = "jsonb_datetime_gte"; + + /** + * Extracts the "value" field from a JSONB column, casts it to TIMESTAMPTZ and compares it with the given value cast to TIMESTAMPTZ, + * returning true if the extracted value is less than the given value. + */ + public static final String JSON_VALUE_DATETIME_LESS_THAN = "jsonb_datetime_lt"; + + /** + * Extracts the "value" field from a JSONB column, casts it to TIMESTAMPTZ and compares it with the given value cast to TIMESTAMPTZ, + * returning true if the extracted value is less than or equal to the given value. + */ + public static final String JSON_VALUE_DATETIME_LESS_THAN_EQUAL = "jsonb_datetime_lte"; + + private static final Map EXTRACTION_FUNCTIONS_BY_TYPE = Map.of( + VariableType.STRING, + EXTRACT_JSON_STRING_VALUE, + VariableType.INTEGER, + EXTRACT_JSON_NUMERIC_VALUE, + VariableType.BIGDECIMAL, + EXTRACT_JSON_NUMERIC_VALUE, + VariableType.DATE, + EXTRACT_JSON_DATE_VALUE, + VariableType.DATETIME, + EXTRACT_JSON_DATETIME_VALUE, + VariableType.BOOLEAN, + EXTRACT_JSON_BOOLEAN_VALUE + ); + + public static String getExtractionFunction(VariableType type) { + return EXTRACTION_FUNCTIONS_BY_TYPE.getOrDefault(type, EXTRACT_JSON_RAW_VALUE); + } + + @Override + public void initializeFunctionRegistry(FunctionContributions functionContributions) { + super.initializeFunctionRegistry(functionContributions); + registerExtractionFunctions(functionContributions); + registerJsonValueEquals(functionContributions); + registerJsonValueLikeFunctions(functionContributions); + registerJsonValueNumericFunctions(functionContributions); + registerJsonValueDateFunctions(functionContributions); + registerJsonValueDatetimeFunctions(functionContributions); + } + + private void registerExtractionFunctions(FunctionContributions functionContributions) { + SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); + String jsonbArgSignature = "JSONB jsonb"; + functionRegistry + .patternDescriptorBuilder(EXTRACT_JSON_RAW_VALUE, "?1->'value'") + .setInvariantType( + functionContributions + .getTypeConfiguration() + .getBasicTypeRegistry() + .resolve(StandardBasicTypes.OBJECT_TYPE) + ) + .setExactArgumentCount(1) + .setArgumentListSignature(jsonbArgSignature) + .register(); + functionRegistry + .patternDescriptorBuilder(EXTRACT_JSON_STRING_VALUE, "?1->>'value'") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.STRING) + ) + .setExactArgumentCount(1) + .setArgumentListSignature(jsonbArgSignature) + .register(); + functionRegistry + .patternDescriptorBuilder(EXTRACT_JSON_NUMERIC_VALUE, "(?1->>'value')::NUMERIC") + .setInvariantType( + functionContributions + .getTypeConfiguration() + .getBasicTypeRegistry() + .resolve(StandardBasicTypes.BIG_DECIMAL) + ) + .setExactArgumentCount(1) + .setArgumentListSignature(jsonbArgSignature) + .register(); + functionRegistry + .patternDescriptorBuilder(EXTRACT_JSON_DATE_VALUE, "(?1->>'value')::DATE") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.DATE) + ) + .setExactArgumentCount(1) + .setArgumentListSignature(jsonbArgSignature) + .register(); + functionRegistry + .patternDescriptorBuilder(EXTRACT_JSON_DATETIME_VALUE, "(?1->>'value')::TIMESTAMPTZ") + .setInvariantType( + functionContributions + .getTypeConfiguration() + .getBasicTypeRegistry() + .resolve(StandardBasicTypes.ZONED_DATE_TIME) + ) + .setExactArgumentCount(1) + .setArgumentListSignature(jsonbArgSignature) + .register(); + functionRegistry + .patternDescriptorBuilder(EXTRACT_JSON_BOOLEAN_VALUE, "(?1->>'value')::BOOLEAN") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(1) + .setArgumentListSignature(jsonbArgSignature) + .register(); + } + + private void registerJsonValueEquals(FunctionContributions functionContributions) { + SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_EQUALS, "?1 @@ '$.value == ?2'") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, ANY value") + .setArgumentTypeResolver((function, argIndex, converter) -> { + if (argIndex == 1 && function.getArguments().get(1).getNodeJavaType().equals(StringJavaType.INSTANCE)) { + return new DoubleQuotedStringType(); + } + return StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE.resolveFunctionArgumentType( + function, + argIndex, + converter + ); + }) + .register(); + } + + private void registerJsonValueLikeFunctions(FunctionContributions functionContributions) { + SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_LIKE_CASE_SENSITIVE, "?1 @@ '$.value like_regex ?2'") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .setArgumentTypeResolver((function, argIndex, converter) -> { + if (argIndex == 1 && function.getArguments().get(1).getNodeJavaType().equals(StringJavaType.INSTANCE)) { + return new DoubleQuotedStringType(RelationalFormType.LIKE_CASE_SENSITIVE); + } + return StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE.resolveFunctionArgumentType( + function, + argIndex, + converter + ); + }) + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_LIKE_CASE_INSENSITIVE, "?1 @@ '$.value like_regex ?2'") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .setArgumentTypeResolver((function, argIndex, converter) -> { + if (argIndex == 1 && function.getArguments().get(1).getNodeJavaType().equals(StringJavaType.INSTANCE)) { + return new DoubleQuotedStringType(RelationalFormType.LIKE_CASE_INSENSITIVE); + } + return StandardFunctionArgumentTypeResolvers.IMPLIED_RESULT_TYPE.resolveFunctionArgumentType( + function, + argIndex, + converter + ); + }) + .register(); + } + + public void registerJsonValueNumericFunctions(FunctionContributions functionContributions) { + SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_NUMERIC_EQUALS, "(?1->>'value')::NUMERIC = ?2") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_NUMERIC_GREATER_THAN, "(?1->>'value')::NUMERIC > ?2") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_NUMERIC_GREATER_THAN_EQUAL, "(?1->>'value')::NUMERIC >= ?2") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_NUMERIC_LESS_THAN, "(?1->>'value')::NUMERIC < ?2") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_NUMERIC_LESS_THAN_EQUAL, "(?1->>'value')::NUMERIC <= ?2") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + } + + private void registerJsonValueDateFunctions(FunctionContributions functionContributions) { + SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATE_EQUALS, "(?1->>'value')::DATE = ?2::DATE") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATE_GREATER_THAN, "(?1->>'value')::DATE > ?2::DATE") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATE_GREATER_THAN_EQUAL, "(?1->>'value')::DATE >= ?2::DATE") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATE_LESS_THAN, "(?1->>'value')::DATE < ?2::DATE") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATE_LESS_THAN_EQUAL, "(?1->>'value')::DATE <= ?2::DATE") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + } + + private void registerJsonValueDatetimeFunctions(FunctionContributions functionContributions) { + SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATETIME_EQUALS, "(?1->>'value')::TIMESTAMPTZ = ?2::TIMESTAMPTZ") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATETIME_GREATER_THAN, "(?1->>'value')::TIMESTAMPTZ > ?2::TIMESTAMPTZ") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder( + JSON_VALUE_DATETIME_GREATER_THAN_EQUAL, + "(?1->>'value')::TIMESTAMPTZ >= ?2::TIMESTAMPTZ" + ) + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder(JSON_VALUE_DATETIME_LESS_THAN, "(?1->>'value')::TIMESTAMPTZ < ?2::TIMESTAMPTZ") + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + functionRegistry + .patternDescriptorBuilder( + JSON_VALUE_DATETIME_LESS_THAN_EQUAL, + "(?1->>'value')::TIMESTAMPTZ <= ?2::TIMESTAMPTZ" + ) + .setInvariantType( + functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN) + ) + .setExactArgumentCount(2) + .setArgumentListSignature("JSONB jsonb, STRING value") + .register(); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/DoubleQuotedStringType.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/DoubleQuotedStringType.java new file mode 100644 index 00000000000..e3943da16bc --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/DoubleQuotedStringType.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.dialect; + +import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; +import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.java.StringJavaType; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; +import org.hibernate.type.descriptor.jdbc.VarcharJdbcType; +import org.hibernate.type.internal.NamedBasicTypeImpl; + +public class DoubleQuotedStringType extends NamedBasicTypeImpl { + + private final RelationalFormType relationalFormType; + + public DoubleQuotedStringType() { + this(RelationalFormType.EQUALS); + } + + public DoubleQuotedStringType(RelationalFormType relationalFormType) { + super(StringJavaType.INSTANCE, VarcharJdbcType.INSTANCE, "doublequotedstring"); + this.relationalFormType = relationalFormType; + } + + @Override + public BasicValueConverter getValueConverter() { + return new BasicValueConverter<>() { + @Override + public String toDomainValue(String relationalForm) { + return relationalForm.replace(".*", "").replace("(?i)", ""); + } + + @Override + public String toRelationalValue(String domainForm) { + return switch (relationalFormType) { + case EQUALS -> domainForm; + case LIKE_CASE_SENSITIVE -> ".*" + domainForm + ".*"; + case LIKE_CASE_INSENSITIVE -> "(?i).*" + domainForm + ".*"; + }; + } + + @Override + public JavaType getDomainJavaType() { + return StringJavaType.INSTANCE; + } + + @Override + public JavaType getRelationalJavaType() { + return StringJavaType.INSTANCE; + } + }; + } + + @Override + public JdbcLiteralFormatter getJdbcLiteralFormatter() { + return (appender, value, dialect, wrapperOptions) -> { + appender.append("\""); + appender.append(value); + appender.append("\""); + }; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/RelationalFormType.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/RelationalFormType.java new file mode 100644 index 00000000000..b48c9cba35a --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/dialect/RelationalFormType.java @@ -0,0 +1,22 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.dialect; + +public enum RelationalFormType { + EQUALS, + LIKE_CASE_SENSITIVE, + LIKE_CASE_INSENSITIVE, +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandler.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandler.java deleted file mode 100644 index edf6bb144b9..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandler.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import jakarta.persistence.EntityManager; -import java.util.Set; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.ProcessInstance.ProcessInstanceStatus; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; -import org.activiti.cloud.api.process.model.events.CloudProcessDeletedEvent; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; - -public class ProcessDeletedEventHandler implements QueryEventHandler { - - protected final String INVALID_PROCESS_INSTANCE_STATE = - "Process Instance %s is not in a valid state: %s. " + - "Only process instances in status COMPLETED or CANCELLED can be deleted."; - - private Set ALLOWED_STATUS = Set.of( - ProcessInstanceStatus.CANCELLED, - ProcessInstanceStatus.COMPLETED - ); - - private final EntityManager entityManager; - private final EntityManagerFinder entityManagerFinder; - - public ProcessDeletedEventHandler(EntityManager entityManager) { - this.entityManager = entityManager; - this.entityManagerFinder = new EntityManagerFinder(entityManager); - } - - @Override - public void handle(CloudRuntimeEvent event) { - CloudProcessDeletedEvent deletedEvent = (CloudProcessDeletedEvent) event; - - ProcessInstance eventProcessInstance = deletedEvent.getEntity(); - - ProcessInstanceEntity processInstanceEntity = entityManagerFinder - .findProcessInstanceWithRelatedEntities(eventProcessInstance.getId()) - .orElseThrow(() -> - new QueryException("Unable to find process instance with the given id: " + eventProcessInstance.getId()) - ); - - if (ALLOWED_STATUS.contains(processInstanceEntity.getStatus())) { - processInstanceEntity.getTasks().stream().forEach(entityManager::remove); - processInstanceEntity.getVariables().stream().forEach(entityManager::remove); - processInstanceEntity.getServiceTasks().stream().forEach(entityManager::remove); - processInstanceEntity.getActivities().stream().forEach(entityManager::remove); - processInstanceEntity.getSequenceFlows().stream().forEach(entityManager::remove); - - entityManager.remove(processInstanceEntity); - } else { - throw new IllegalStateException( - String.format( - INVALID_PROCESS_INSTANCE_STATE, - processInstanceEntity.getId(), - processInstanceEntity.getStatus().name() - ) - ); - } - } - - @Override - public String getHandledEvent() { - return ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED.name(); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/CommonExceptionHandlerQuery.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/CommonExceptionHandlerQuery.java index 849eebbad6b..de3c4de4109 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/CommonExceptionHandlerQuery.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/CommonExceptionHandlerQuery.java @@ -15,12 +15,14 @@ */ package org.activiti.cloud.services.query.rest; +import jakarta.persistence.EntityNotFoundException; import jakarta.servlet.http.HttpServletResponse; import org.activiti.api.model.shared.model.ActivitiErrorMessage; import org.activiti.api.runtime.model.impl.ActivitiErrorMessageImpl; import org.activiti.core.common.spring.security.policies.ActivitiForbiddenException; import org.springframework.hateoas.EntityModel; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -38,4 +40,24 @@ public EntityModel handleAppException( response.setContentType("application/json"); return EntityModel.of(new ActivitiErrorMessageImpl(HttpStatus.FORBIDDEN.value(), ex.getMessage())); } + + @ExceptionHandler(IllegalStateException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public EntityModel handleAppException( + IllegalStateException ex, + HttpServletResponse response + ) { + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + return EntityModel.of(new ActivitiErrorMessageImpl(HttpStatus.BAD_REQUEST.value(), ex.getMessage())); + } + + @ExceptionHandler(EntityNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public EntityModel handleAppException( + EntityNotFoundException ex, + HttpServletResponse response + ) { + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + return EntityModel.of(new ActivitiErrorMessageImpl(HttpStatus.NOT_FOUND.value(), ex.getMessage())); + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java index 4f9ff539631..f31b51ccf32 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminController.java @@ -15,7 +15,10 @@ */ package org.activiti.cloud.services.query.rest; -import static org.activiti.cloud.services.query.rest.RestDocConstants.*; +import static org.activiti.cloud.services.query.rest.RestDocConstants.PREDICATE_DESC; +import static org.activiti.cloud.services.query.rest.RestDocConstants.PREDICATE_EXAMPLE; +import static org.activiti.cloud.services.query.rest.RestDocConstants.VARIABLE_KEYS_DESC; +import static org.activiti.cloud.services.query.rest.RestDocConstants.VARIABLE_KEYS_EXAMPLE; import com.fasterxml.jackson.annotation.JsonView; import com.querydsl.core.types.Predicate; @@ -24,12 +27,14 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import org.activiti.cloud.alfresco.data.domain.AlfrescoPagedModelAssembler; import org.activiti.cloud.api.process.model.CloudProcessInstance; import org.activiti.cloud.services.query.model.JsonViews; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.rest.assembler.ProcessInstanceRepresentationModelAssembler; import org.activiti.cloud.services.query.rest.payload.ProcessInstanceQueryBody; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.querydsl.binding.QuerydslPredicate; @@ -38,7 +43,13 @@ import org.springframework.hateoas.PagedModel; import org.springframework.http.MediaType; import org.springframework.http.converter.json.MappingJacksonValue; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping( @@ -132,6 +143,20 @@ public MappingJacksonValue findAllFromBodyProcessAdmin( return result; } + @Operation(summary = "Search process instances") + @JsonView(JsonViews.ProcessVariables.class) + @PostMapping("/search") + public PagedModel> searchProcessInstances( + @RequestBody ProcessInstanceSearchRequest searchRequest, + Pageable pageable + ) { + return pagedCollectionModelAssembler.toModel( + pageable, + processInstanceAdminService.search(searchRequest, pageable), + processInstanceRepresentationModelAssembler + ); + } + @JsonView(JsonViews.General.class) @RequestMapping(value = "/{processInstanceId}", method = RequestMethod.GET) public EntityModel findByIdProcessAdmin(@PathVariable String processInstanceId) { @@ -139,4 +164,14 @@ public EntityModel findByIdProcessAdmin(@PathVariable Stri processInstanceAdminService.findById(processInstanceId) ); } + + @Operation(summary = "Find application versions for process instances") + @RequestMapping(value = "/appVersions", method = RequestMethod.GET) + public Set findProcessAppVersions( + @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( + root = ProcessInstanceEntity.class + ) Predicate predicate + ) { + return processInstanceAdminService.findAllAppVersions(predicate); + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminService.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminService.java index 70112cb7744..032a84ed989 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminService.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceAdminService.java @@ -17,14 +17,20 @@ import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.transaction.Transactional; import java.util.List; +import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import org.activiti.cloud.services.query.app.repository.EntityFinder; import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.QProcessInstanceEntity; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; import org.activiti.cloud.services.query.rest.predicate.QueryDslPredicateAggregator; import org.activiti.cloud.services.query.rest.predicate.QueryDslPredicateFilter; import org.hibernate.Filter; @@ -32,12 +38,15 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; public class ProcessInstanceAdminService { private final ProcessInstanceRepository processInstanceRepository; + private final ProcessInstanceSearchService processInstanceSearchService; + private final EntityFinder entityFinder; private final QueryDslPredicateAggregator predicateAggregator; @@ -47,10 +56,12 @@ public class ProcessInstanceAdminService { public ProcessInstanceAdminService( ProcessInstanceRepository processInstanceRepository, + ProcessInstanceSearchService processInstanceSearchService, EntityFinder entityFinder, QueryDslPredicateAggregator queryDslPredicateAggregator ) { this.processInstanceRepository = processInstanceRepository; + this.processInstanceSearchService = processInstanceSearchService; this.entityFinder = entityFinder; this.predicateAggregator = queryDslPredicateAggregator; } @@ -76,7 +87,7 @@ public Page findAllFromBody( } } - @Transactional + @Transactional(readOnly = true) public Page findAllWithVariables( Predicate predicate, List variableKeys, @@ -96,7 +107,27 @@ public ProcessInstanceEntity findById(@PathVariable String processInstanceId) { return entityFinder.findById( processInstanceRepository, processInstanceId, - "Unable to find task for the given id:'" + processInstanceId + "'" + "Unable to find process instance for the given id:'" + processInstanceId + "'" ); } + + public Set findAllAppVersions(Predicate predicate) { + Predicate transformedPredicate = Optional.ofNullable(predicate).orElseGet(BooleanBuilder::new); + JPAQuery query = new JPAQueryFactory(entityManager).query(); + + QProcessInstanceEntity process = QProcessInstanceEntity.processInstanceEntity; + List appVersions = query + .select(process.appVersion) + .distinct() + .from(process) + .where(transformedPredicate) + .fetch(); + + return appVersions.stream().filter(Objects::nonNull).collect(Collectors.toSet()); + } + + @Transactional(readOnly = true) + public Page search(ProcessInstanceSearchRequest searchRequest, Pageable pageable) { + return processInstanceSearchService.searchUnrestricted(searchRequest, pageable); + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java index a00eb5273a7..b5b36cdeb5f 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceController.java @@ -24,13 +24,13 @@ import com.querydsl.core.types.Predicate; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; import org.activiti.cloud.alfresco.data.domain.AlfrescoPagedModelAssembler; import org.activiti.cloud.api.process.model.CloudProcessInstance; import org.activiti.cloud.services.query.model.JsonViews; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.rest.assembler.ProcessInstanceRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.querydsl.binding.QuerydslPredicate; @@ -39,6 +39,8 @@ import org.springframework.hateoas.PagedModel; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -105,6 +107,20 @@ public PagedModel> findAllWithVariables( ); } + @Operation(summary = "Search process instances") + @JsonView(JsonViews.ProcessVariables.class) + @PostMapping("/search") + public PagedModel> searchProcessInstances( + @RequestBody ProcessInstanceSearchRequest searchRequest, + Pageable pageable + ) { + return pagedCollectionModelAssembler.toModel( + pageable, + processInstanceService.search(searchRequest, pageable), + processInstanceRepresentationModelAssembler + ); + } + @JsonView(JsonViews.General.class) @RequestMapping(value = "/{processInstanceId}", method = RequestMethod.GET) public EntityModel findByIdProcess(@PathVariable String processInstanceId) { diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceSearchService.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceSearchService.java new file mode 100644 index 00000000000..67d278b1f75 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceSearchService.java @@ -0,0 +1,90 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import java.util.Set; +import org.activiti.api.runtime.shared.security.SecurityManager; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; +import org.activiti.cloud.services.query.rest.specification.ProcessInstanceSpecification; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.transaction.annotation.Transactional; + +public class ProcessInstanceSearchService { + + private final ProcessInstanceRepository processInstanceRepository; + + private final ProcessVariableService processVariableService; + + private final SecurityManager securityManager; + + public ProcessInstanceSearchService( + ProcessInstanceRepository processInstanceRepository, + ProcessVariableService processVariableService, + SecurityManager securityManager + ) { + this.processInstanceRepository = processInstanceRepository; + this.processVariableService = processVariableService; + this.securityManager = securityManager; + } + + @Transactional(readOnly = true) + public Page searchRestricted(ProcessInstanceSearchRequest searchRequest, Pageable pageable) { + return search( + searchRequest.processVariableKeys(), + pageable, + ProcessInstanceSpecification.restricted(searchRequest, securityManager.getAuthenticatedUserId()) + ); + } + + @Transactional(readOnly = true) + public Page searchUnrestricted( + ProcessInstanceSearchRequest searchRequest, + Pageable pageable + ) { + return search( + searchRequest.processVariableKeys(), + pageable, + ProcessInstanceSpecification.unrestricted(searchRequest) + ); + } + + /** + * @param processVariableKeys the process variables to fetch for each process instance, each represented by process definition key and variable name + * @param pageable the page request. N.B. the sort contained in this pageable will be ignored and the sort from the search request will be used instead + * @param specification the specification to use for the search. It includes the sorting parameter. + * @return the page of process instances + */ + private Page search( + Set processVariableKeys, + Pageable pageable, + ProcessInstanceSpecification specification + ) { + Page processInstances = processInstanceRepository.findAll( + specification, + PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()) + ); + processVariableService.fetchProcessVariablesForProcessInstances( + processInstances.getContent(), + processVariableKeys + ); + return processInstances; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceService.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceService.java index 0f473057d98..47ea5580f6c 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceService.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessInstanceService.java @@ -21,7 +21,6 @@ import com.querydsl.core.types.dsl.BooleanExpression; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.transaction.Transactional; import java.util.List; import java.util.Optional; import org.activiti.api.runtime.shared.security.SecurityManager; @@ -31,6 +30,7 @@ import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.query.model.QProcessInstanceEntity; import org.activiti.cloud.services.query.model.QTaskEntity; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; import org.activiti.cloud.services.security.ProcessInstanceRestrictionService; import org.activiti.core.common.spring.security.policies.ActivitiForbiddenException; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -42,6 +42,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.transaction.annotation.Transactional; public class ProcessInstanceService { @@ -51,6 +52,8 @@ public class ProcessInstanceService { private final TaskRepository taskRepository; + private final ProcessInstanceSearchService processInstanceSearchService; + private final ProcessInstanceRestrictionService processInstanceRestrictionService; private final SecurityPoliciesManager securityPoliciesApplicationService; @@ -65,6 +68,7 @@ public class ProcessInstanceService { public ProcessInstanceService( ProcessInstanceRepository processInstanceRepository, TaskRepository taskRepository, + ProcessInstanceSearchService processInstanceSearchService, ProcessInstanceRestrictionService processInstanceRestrictionService, SecurityPoliciesManager securityPoliciesApplicationService, SecurityManager securityManager, @@ -72,6 +76,7 @@ public ProcessInstanceService( ) { this.processInstanceRepository = processInstanceRepository; this.taskRepository = taskRepository; + this.processInstanceSearchService = processInstanceSearchService; this.processInstanceRestrictionService = processInstanceRestrictionService; this.securityPoliciesApplicationService = securityPoliciesApplicationService; this.securityManager = securityManager; @@ -161,6 +166,11 @@ public Page subprocesses(String processInstanceId, Predic return processInstanceRepository.findAll(extendedPredicate, pageable); } + @Transactional(readOnly = true) + public Page search(ProcessInstanceSearchRequest searchRequest, Pageable pageable) { + return processInstanceSearchService.searchRestricted(searchRequest, pageable); + } + private boolean canRead(ProcessInstanceEntity processInstanceEntity) { return ( securityPoliciesApplicationService.canRead( diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessVariableService.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessVariableService.java new file mode 100644 index 00000000000..27af208428d --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/ProcessVariableService.java @@ -0,0 +1,110 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.activiti.cloud.api.task.model.QueryCloudTask; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.rest.specification.ProcessVariableSpecification; +import org.springframework.util.CollectionUtils; + +public class ProcessVariableService { + + private final VariableRepository variableRepository; + + public ProcessVariableService(VariableRepository variableRepository) { + this.variableRepository = variableRepository; + } + + public void fetchProcessVariablesForProcessInstances( + Collection processInstances, + Set variableKeys + ) { + if (!CollectionUtils.isEmpty(variableKeys)) { + Set processInstanceIds = processInstances + .stream() + .map(ProcessInstanceEntity::getId) + .collect(Collectors.toSet()); + + Map> processVariablesMap = fetchVariablesInternal( + processInstanceIds, + variableKeys + ); + processInstances.forEach(pi -> + pi.setVariables(processVariablesMap.getOrDefault(pi.getId(), Collections.emptySet())) + ); + } else { + processInstances.forEach(pi -> pi.setVariables(Collections.emptySet())); + } + } + + public void fetchProcessVariablesForTasks( + Collection tasks, + Collection processVariableFetchKeys + ) { + fetchProcessVariablesForTasks( + tasks, + processVariableFetchKeys.stream().map(ProcessVariableKey::fromString).collect(Collectors.toSet()) + ); + } + + public void fetchProcessVariablesForTasks( + Collection tasks, + Set processVariableFetchKeys + ) { + if (!CollectionUtils.isEmpty(processVariableFetchKeys)) { + Set processInstanceIds = tasks + .stream() + .map(QueryCloudTask::getProcessInstanceId) + .collect(Collectors.toSet()); + + Map> processVariablesMap = fetchVariablesInternal( + processInstanceIds, + processVariableFetchKeys + ); + tasks.forEach(task -> + task.setProcessVariables( + processVariablesMap.getOrDefault(task.getProcessInstanceId(), Collections.emptySet()) + ) + ); + } else { + tasks.forEach(task -> task.setProcessVariables(Collections.emptySet())); + } + } + + private Map> fetchVariablesInternal( + Set processInstanceIds, + Set processVariableFetchKeys + ) { + List processVariables = variableRepository.findBy( + new ProcessVariableSpecification(processInstanceIds, processVariableFetchKeys), + q -> q.project(ProcessVariableEntity_.VALUE).all() + ); + return processVariables + .stream() + .collect(Collectors.groupingBy(ProcessVariableEntity::getProcessInstanceId, Collectors.toSet())); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskAdminController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskAdminController.java index 26ef94facbc..9b56ee1d7b5 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskAdminController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskAdminController.java @@ -38,6 +38,7 @@ import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.query.rest.assembler.TaskRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.payload.TaskSearchRequest; import org.activiti.cloud.services.query.rest.payload.TasksQueryBody; import org.activiti.cloud.services.query.rest.predicate.RootTasksFilter; import org.activiti.cloud.services.query.rest.predicate.StandAloneTaskFilter; @@ -50,6 +51,7 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.json.MappingJacksonValue; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -139,6 +141,16 @@ public PagedModel> findAllWithProcessVariablesAdmin( ); } + @Operation(summary = "Search tasks") + @JsonView(JsonViews.General.class) + @PostMapping("/search") + public PagedModel> searchTasks( + @RequestBody TaskSearchRequest taskSearchRequest, + Pageable pageable + ) { + return taskControllerHelper.searchTasksUnrestricted(taskSearchRequest, pageable); + } + @RequestMapping(method = RequestMethod.POST) public MappingJacksonValue findAllFromBodyTaskAdmin( @Parameter(description = PREDICATE_DESC, example = PREDICATE_EXAMPLE) @QuerydslPredicate( diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskController.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskController.java index b1a5f0f3933..d40a73f2ed7 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskController.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskController.java @@ -40,6 +40,7 @@ import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.query.rest.assembler.TaskRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.payload.TaskSearchRequest; import org.activiti.cloud.services.query.rest.predicate.RootTasksFilter; import org.activiti.cloud.services.query.rest.predicate.StandAloneTaskFilter; import org.activiti.cloud.services.security.TaskLookupRestrictionService; @@ -53,6 +54,8 @@ import org.springframework.hateoas.PagedModel; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -126,6 +129,16 @@ public PagedModel> findAllTasks( ); } + @Operation(summary = "Search tasks") + @JsonView(JsonViews.General.class) + @PostMapping("/search") + public PagedModel> searchTasks( + @RequestBody TaskSearchRequest taskSearchRequest, + Pageable pageable + ) { + return taskControllerHelper.searchTasksRestricted(taskSearchRequest, pageable); + } + @Operation(summary = "Find tasks") @JsonView(JsonViews.ProcessVariables.class) @RequestMapping(method = RequestMethod.GET, params = "variableKeys") diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskControllerHelper.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskControllerHelper.java index 0197d11b9b5..e1d7b5f67e2 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskControllerHelper.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/TaskControllerHelper.java @@ -17,20 +17,18 @@ package org.activiti.cloud.services.query.rest; import com.querydsl.core.types.Predicate; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; import java.util.List; +import org.activiti.api.runtime.shared.security.SecurityManager; import org.activiti.cloud.alfresco.data.domain.AlfrescoPagedModelAssembler; import org.activiti.cloud.api.task.model.QueryCloudTask; import org.activiti.cloud.services.query.app.repository.TaskRepository; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.query.rest.assembler.TaskRepresentationModelAssembler; +import org.activiti.cloud.services.query.rest.payload.TaskSearchRequest; import org.activiti.cloud.services.query.rest.predicate.QueryDslPredicateAggregator; import org.activiti.cloud.services.query.rest.predicate.QueryDslPredicateFilter; +import org.activiti.cloud.services.query.rest.specification.TaskSpecification; import org.activiti.cloud.services.security.TaskLookupRestrictionService; -import org.hibernate.Filter; -import org.hibernate.Hibernate; -import org.hibernate.Session; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.hateoas.EntityModel; @@ -41,6 +39,8 @@ public class TaskControllerHelper { private final TaskRepository taskRepository; + private final ProcessVariableService processVariableService; + private final AlfrescoPagedModelAssembler pagedCollectionModelAssembler; private final QueryDslPredicateAggregator predicateAggregator; @@ -49,21 +49,24 @@ public class TaskControllerHelper { private final TaskLookupRestrictionService taskLookupRestrictionService; - @PersistenceContext - private EntityManager entityManager; + private final SecurityManager securityManager; public TaskControllerHelper( TaskRepository taskRepository, + ProcessVariableService processVariableService, AlfrescoPagedModelAssembler pagedCollectionModelAssembler, QueryDslPredicateAggregator predicateAggregator, TaskRepresentationModelAssembler taskRepresentationModelAssembler, - TaskLookupRestrictionService taskLookupRestrictionService + TaskLookupRestrictionService taskLookupRestrictionService, + SecurityManager securityManager ) { this.taskRepository = taskRepository; + this.processVariableService = processVariableService; this.pagedCollectionModelAssembler = pagedCollectionModelAssembler; this.predicateAggregator = predicateAggregator; this.taskRepresentationModelAssembler = taskRepresentationModelAssembler; this.taskLookupRestrictionService = taskLookupRestrictionService; + this.securityManager = securityManager; } public PagedModel> findAll( @@ -84,14 +87,46 @@ public PagedModel> findAllWithProcessVariables( List filters, List processVariableKeys ) { - Page page = findPageWithProcessVariables( - predicate, - variableSearch, + Page page = findPageWithProcessVariables(predicate, variableSearch, pageable, filters); + processVariableService.fetchProcessVariablesForTasks(page.getContent(), processVariableKeys); + return pagedCollectionModelAssembler.toModel(pageable, page, taskRepresentationModelAssembler); + } + + @Transactional(readOnly = true) + public PagedModel> searchTasksRestricted( + TaskSearchRequest taskSearchRequest, + Pageable pageable + ) { + return searchTasks( + taskSearchRequest, pageable, - filters, - processVariableKeys + TaskSpecification.restricted( + taskSearchRequest, + securityManager.getAuthenticatedUserId(), + securityManager.getAuthenticatedUserGroups() + ) ); - return pagedCollectionModelAssembler.toModel(pageable, page, taskRepresentationModelAssembler); + } + + @Transactional(readOnly = true) + public PagedModel> searchTasksUnrestricted( + TaskSearchRequest taskSearchRequest, + Pageable pageable + ) { + return searchTasks(taskSearchRequest, pageable, TaskSpecification.unrestricted(taskSearchRequest)); + } + + private PagedModel> searchTasks( + TaskSearchRequest taskSearchRequest, + Pageable pageable, + TaskSpecification taskSpecification + ) { + Page tasks = taskRepository.findAll(taskSpecification, pageable); + processVariableService.fetchProcessVariablesForTasks( + tasks.getContent(), + taskSearchRequest.processVariableKeys() + ); + return pagedCollectionModelAssembler.toModel(pageable, tasks, taskRepresentationModelAssembler); } public PagedModel> findAllByInvolvedUserQuery(Predicate predicate, Pageable pageable) { @@ -120,22 +155,11 @@ public PagedModel> findAllByInvolvedUserQueryWithPro List processVariableKeys, Pageable pageable ) { - addProcessVariablesFilter(processVariableKeys); Page page = findAllByInvolvedUser(predicate, pageable); - initializeProcessVariables(page); + processVariableService.fetchProcessVariablesForTasks(page.getContent(), processVariableKeys); return pagedCollectionModelAssembler.toModel(pageable, page, taskRepresentationModelAssembler); } - private void initializeProcessVariables(Page page) { - page.forEach(taskEntity -> Hibernate.initialize(taskEntity.getProcessVariables())); - } - - private void addProcessVariablesFilter(List processVariableKeys) { - Session session = entityManager.unwrap(Session.class); - Filter filter = session.enableFilter("variablesFilter"); - filter.setParameterList("variableKeys", processVariableKeys); - } - private Page findAllByInvolvedUser(Predicate predicate, Pageable pageable) { Predicate conditions = taskLookupRestrictionService.restrictToInvolvedUsersQuery(predicate); return taskRepository.findInProcessInstanceScope(conditions, pageable); @@ -173,13 +197,10 @@ private Page findPageWithProcessVariables( Predicate predicate, VariableSearch variableSearch, Pageable pageable, - List filters, - List processVariableKeys + List filters ) { Predicate extendedPredicate = predicateAggregator.applyFilters(predicate, filters); - if (variableSearch.isSet()) { - addProcessVariablesFilter(processVariableKeys); return taskRepository.findByVariableNameAndValue( variableSearch.getName(), variableSearch.getValue(), @@ -187,7 +208,7 @@ private Page findPageWithProcessVariables( pageable ); } else { - return taskRepository.findWithProcessVariables(processVariableKeys, extendedPredicate, pageable); + return taskRepository.findAll(extendedPredicate, pageable); } } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/config/CustomHibernateAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/config/CustomHibernateAutoConfiguration.java new file mode 100644 index 00000000000..8193cd8f622 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/config/CustomHibernateAutoConfiguration.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.config; + +import java.util.Map; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; + +@AutoConfiguration(after = DataSourceAutoConfiguration.class) +@ConditionalOnExpression( + "'${spring.jpa.database-platform}'.toLowerCase().contains('postgres') or '${spring.datasource.url}'.toLowerCase().contains('postgres')" +) +public class CustomHibernateAutoConfiguration implements HibernatePropertiesCustomizer { + + @Override + public void customize(Map hibernateProperties) { + hibernateProperties.put("hibernate.dialect", CustomPostgreSQLDialect.class.getName()); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/exception/IllegalFilterException.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/exception/IllegalFilterException.java new file mode 100644 index 00000000000..e0e179408c8 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/exception/IllegalFilterException.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.exception; + +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class IllegalFilterException extends IllegalArgumentException { + + public IllegalFilterException(VariableType type, FilterOperator operator) { + super("Unsupported type: " + type + " for operator: " + operator); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/FilterOperator.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/FilterOperator.java new file mode 100644 index 00000000000..ba4e031e32f --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/FilterOperator.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.filter; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum FilterOperator { + @JsonProperty("eq") + EQUALS, + @JsonProperty("like") + LIKE, + @JsonProperty("gt") + GREATER_THAN, + @JsonProperty("gte") + GREATER_THAN_OR_EQUAL, + @JsonProperty("lt") + LESS_THAN, + @JsonProperty("lte") + LESS_THAN_OR_EQUAL, +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/VariableFilter.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/VariableFilter.java new file mode 100644 index 00000000000..25b893d5a16 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/VariableFilter.java @@ -0,0 +1,22 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.filter; + +import jakarta.annotation.Nullable; + +public record VariableFilter( + @Nullable String processDefinitionKey, String name, VariableType type, String value, FilterOperator operator +) {} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/VariableType.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/VariableType.java new file mode 100644 index 00000000000..8df24fd6dac --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/filter/VariableType.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.filter; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum VariableType { + STRING, + INTEGER, + BIGDECIMAL, + BOOLEAN, + DATE, + DATETIME; + + @JsonValue + public String getValue() { + return name().toLowerCase(); + } + + public static VariableType fromString(String name) { + try { + return VariableType.valueOf(name.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(String.format("Cannot determine variable type from '%s'", name)); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/CloudRuntimeEntitySort.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/CloudRuntimeEntitySort.java new file mode 100644 index 00000000000..72362ebaebe --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/CloudRuntimeEntitySort.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.payload; + +import com.fasterxml.jackson.annotation.JsonCreator; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.springframework.data.domain.Sort; + +public record CloudRuntimeEntitySort( + String field, Sort.Direction direction, boolean isProcessVariable, String processDefinitionKey, VariableType type +) { + /** + * This constructor's purpose is to make deserialization of 'direction' case-insensitive. + */ + @JsonCreator + public CloudRuntimeEntitySort( + String field, + String direction, + boolean isProcessVariable, + String processDefinitionKey, + VariableType type + ) { + this( + field, + Sort.Direction.fromString(direction), + isProcessVariable, + processDefinitionKey, + type == null ? null : VariableType.fromString(type.name()) + ); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/ProcessInstanceSearchRequest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/ProcessInstanceSearchRequest.java new file mode 100644 index 00000000000..b2631aca934 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/ProcessInstanceSearchRequest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.payload; + +import java.util.Date; +import java.util.Set; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; + +//prettier-ignore +public record ProcessInstanceSearchRequest( + Set name, + Set initiator, + Set appVersion, + Date lastModifiedFrom, + Date lastModifiedTo, + Date startFrom, + Date startTo, + Date completedFrom, + Date completedTo, + Date suspendedFrom, + Date suspendedTo, + Set processVariableFilters, + Set processVariableKeys, + CloudRuntimeEntitySort sort +) {} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/TaskSearchRequest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/TaskSearchRequest.java new file mode 100644 index 00000000000..b8e025ce156 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/payload/TaskSearchRequest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.payload; + +import java.util.Date; +import java.util.Set; +import org.activiti.api.task.model.Task; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; + +//prettier-ignore +public record TaskSearchRequest( + boolean onlyStandalone, + boolean onlyRoot, + Set name, + Set description, + Set processDefinitionName, + Set priority, + Set status, + Set completedBy, + Set assignee, + Date createdFrom, + Date createdTo, + Date lastModifiedFrom, + Date lastModifiedTo, + Date lastClaimedFrom, + Date lastClaimedTo, + Date dueDateFrom, + Date dueDateTo, + Date completedFrom, + Date completedTo, + Set candidateUserId, + Set candidateGroupId, + Set taskVariableFilters, + Set processVariableFilters, + Set processVariableKeys +) {} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/BigDecimalVariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/BigDecimalVariableValueCondition.java new file mode 100644 index 00000000000..22646653e1b --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/BigDecimalVariableValueCondition.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.rest.exception.IllegalFilterException; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class BigDecimalVariableValueCondition extends VariableValueCondition { + + public BigDecimalVariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + super(path, operator, value, criteriaBuilder); + } + + @Override + protected String getFunctionName() { + return switch (operator) { + case EQUALS -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_EQUALS; + case GREATER_THAN -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_GREATER_THAN; + case GREATER_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_GREATER_THAN_EQUAL; + case LESS_THAN -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_LESS_THAN; + case LESS_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_LESS_THAN_EQUAL; + default -> throw new IllegalFilterException(VariableType.BIGDECIMAL, operator); + }; + } + + @Override + protected Object getConvertedValue() { + return value; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/BooleanVariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/BooleanVariableValueCondition.java new file mode 100644 index 00000000000..1c8d6d4aba7 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/BooleanVariableValueCondition.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.rest.exception.IllegalFilterException; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class BooleanVariableValueCondition extends VariableValueCondition { + + public BooleanVariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + super(path, operator, value, criteriaBuilder); + } + + @Override + protected String getFunctionName() { + if (operator == FilterOperator.EQUALS) { + return CustomPostgreSQLDialect.JSON_VALUE_EQUALS; + } + throw new IllegalFilterException(VariableType.BOOLEAN, operator); + } + + @Override + protected Boolean getConvertedValue() { + return Boolean.parseBoolean(value); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/DateVariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/DateVariableValueCondition.java new file mode 100644 index 00000000000..1fff8dc53ba --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/DateVariableValueCondition.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.rest.exception.IllegalFilterException; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class DateVariableValueCondition extends VariableValueCondition { + + public DateVariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + super(path, operator, value, criteriaBuilder); + } + + @Override + protected String getFunctionName() { + return switch (operator) { + case EQUALS -> CustomPostgreSQLDialect.JSON_VALUE_DATE_EQUALS; + case GREATER_THAN -> CustomPostgreSQLDialect.JSON_VALUE_DATE_GREATER_THAN; + case GREATER_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_DATE_GREATER_THAN_EQUAL; + case LESS_THAN -> CustomPostgreSQLDialect.JSON_VALUE_DATE_LESS_THAN; + case LESS_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_DATE_LESS_THAN_EQUAL; + default -> throw new IllegalFilterException(VariableType.DATE, operator); + }; + } + + @Override + protected String getConvertedValue() { + return value; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/DatetimeVariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/DatetimeVariableValueCondition.java new file mode 100644 index 00000000000..97cce5c5c8f --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/DatetimeVariableValueCondition.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.rest.exception.IllegalFilterException; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class DatetimeVariableValueCondition extends VariableValueCondition { + + public DatetimeVariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + super(path, operator, value, criteriaBuilder); + } + + @Override + protected String getFunctionName() { + return switch (operator) { + case EQUALS -> CustomPostgreSQLDialect.JSON_VALUE_DATETIME_EQUALS; + case GREATER_THAN -> CustomPostgreSQLDialect.JSON_VALUE_DATETIME_GREATER_THAN; + case GREATER_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_DATETIME_GREATER_THAN_EQUAL; + case LESS_THAN -> CustomPostgreSQLDialect.JSON_VALUE_DATETIME_LESS_THAN; + case LESS_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_DATETIME_LESS_THAN_EQUAL; + default -> throw new IllegalFilterException(VariableType.DATETIME, operator); + }; + } + + @Override + protected String getConvertedValue() { + return value; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/IntegerVariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/IntegerVariableValueCondition.java new file mode 100644 index 00000000000..1b65a5d4b53 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/IntegerVariableValueCondition.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.rest.exception.IllegalFilterException; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class IntegerVariableValueCondition extends VariableValueCondition { + + public IntegerVariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + super(path, operator, value, criteriaBuilder); + } + + @Override + protected String getFunctionName() { + return switch (operator) { + case EQUALS -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_EQUALS; + case GREATER_THAN -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_GREATER_THAN; + case GREATER_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_GREATER_THAN_EQUAL; + case LESS_THAN -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_LESS_THAN; + case LESS_THAN_OR_EQUAL -> CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_LESS_THAN_EQUAL; + default -> throw new IllegalFilterException(VariableType.INTEGER, operator); + }; + } + + @Override + protected Integer getConvertedValue() { + return Integer.parseInt(value); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/ProcessInstanceSpecification.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/ProcessInstanceSpecification.java new file mode 100644 index 00000000000..974af36221f --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/ProcessInstanceSpecification.java @@ -0,0 +1,206 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity_; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.activiti.cloud.services.query.model.TaskCandidateUserEntity_; +import org.activiti.cloud.services.query.model.TaskEntity_; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; +import org.springframework.util.CollectionUtils; + +public class ProcessInstanceSpecification extends SpecificationSupport { + + List predicates = new ArrayList<>(); + + private final String userId; + + private final ProcessInstanceSearchRequest searchRequest; + + private ProcessInstanceSpecification(ProcessInstanceSearchRequest searchRequest, String userId) { + this.searchRequest = searchRequest; + this.userId = userId; + } + + public static ProcessInstanceSpecification unrestricted(ProcessInstanceSearchRequest searchRequest) { + return new ProcessInstanceSpecification(searchRequest, null); + } + + public static ProcessInstanceSpecification restricted(ProcessInstanceSearchRequest searchRequest, String userId) { + return new ProcessInstanceSpecification(searchRequest, userId); + } + + @Override + public Predicate toPredicate( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + applyUserRestrictionFilter(root, criteriaBuilder); + applyNameFilter(root, criteriaBuilder); + applyInitiatorFilter(root); + applyAppVersionFilter(root); + applyLastModifiedDateFilters(root, criteriaBuilder); + applyStartFilters(root, criteriaBuilder); + applyCompletedFilters(root, criteriaBuilder); + applySuspendedFilters(root, criteriaBuilder); + applyProcessVariableFilters(root, query, criteriaBuilder); + applySorting( + root, + () -> root.join(ProcessInstanceEntity_.variables, JoinType.LEFT), + searchRequest.sort(), + query, + criteriaBuilder + ); + if (predicates.isEmpty()) { + return criteriaBuilder.conjunction(); + } + return criteriaBuilder.and(predicates.toArray(Predicate[]::new)); + } + + private void applyNameFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (!CollectionUtils.isEmpty(searchRequest.name())) { + addLikeFilters(predicates, searchRequest.name(), root, criteriaBuilder, ProcessInstanceEntity_.name); + } + } + + private void applyInitiatorFilter(Root root) { + if (!CollectionUtils.isEmpty(searchRequest.initiator())) { + predicates.add(root.get(ProcessInstanceEntity_.initiator).in(searchRequest.initiator())); + } + } + + private void applyAppVersionFilter(Root root) { + if (!CollectionUtils.isEmpty(searchRequest.appVersion())) { + predicates.add(root.get(ProcessInstanceEntity_.appVersion).in(searchRequest.appVersion())); + } + } + + private void applyLastModifiedDateFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (searchRequest.lastModifiedFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan( + root.get(ProcessInstanceEntity_.lastModified), + searchRequest.lastModifiedFrom() + ) + ); + } + if (searchRequest.lastModifiedTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(ProcessInstanceEntity_.lastModified), searchRequest.lastModifiedTo()) + ); + } + } + + private void applyStartFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (searchRequest.startFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan(root.get(ProcessInstanceEntity_.startDate), searchRequest.startFrom()) + ); + } + if (searchRequest.startTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(ProcessInstanceEntity_.startDate), searchRequest.startTo()) + ); + } + } + + private void applyCompletedFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (searchRequest.completedFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan( + root.get(ProcessInstanceEntity_.completedDate), + searchRequest.completedFrom() + ) + ); + } + if (searchRequest.completedTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(ProcessInstanceEntity_.completedDate), searchRequest.completedTo()) + ); + } + } + + private void applySuspendedFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (searchRequest.suspendedFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan( + root.get(ProcessInstanceEntity_.suspendedDate), + searchRequest.suspendedFrom() + ) + ); + } + if (searchRequest.suspendedTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(ProcessInstanceEntity_.suspendedDate), searchRequest.suspendedTo()) + ); + } + } + + private void applyUserRestrictionFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (userId != null) { + predicates.add( + criteriaBuilder.or( + criteriaBuilder.equal(root.get(ProcessInstanceEntity_.initiator), userId), + criteriaBuilder.equal( + root.join(ProcessInstanceEntity_.tasks, JoinType.LEFT).get(TaskEntity_.assignee), + userId + ), + criteriaBuilder.equal( + root + .join(ProcessInstanceEntity_.tasks, JoinType.LEFT) + .join(TaskEntity_.taskCandidateUsers, JoinType.LEFT) + .get(TaskCandidateUserEntity_.userId), + userId + ) + ) + ); + } + } + + private void applyProcessVariableFilters( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + if (!CollectionUtils.isEmpty(searchRequest.processVariableFilters())) { + Root pvRoot = query.from(ProcessVariableEntity.class); + Predicate joinCondition = criteriaBuilder.equal( + root.get(ProcessInstanceEntity_.id), + pvRoot.get(ProcessVariableEntity_.processInstanceId) + ); + + Predicate[] variableValueFilters = getProcessVariableValueFilters( + pvRoot, + searchRequest.processVariableFilters(), + criteriaBuilder + ); + + query.groupBy(root.get(ProcessInstanceEntity_.id)); + query.having(getHavingClause(pvRoot, searchRequest.processVariableFilters(), criteriaBuilder)); + predicates.add(criteriaBuilder.and(joinCondition, criteriaBuilder.or(variableValueFilters))); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/ProcessVariableSpecification.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/ProcessVariableSpecification.java new file mode 100644 index 00000000000..fb036a325fa --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/ProcessVariableSpecification.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import java.util.Set; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.springframework.data.jpa.domain.Specification; + +public class ProcessVariableSpecification implements Specification { + + private final Set processInstanceIds; + private final Set processVariableKeys; + + public ProcessVariableSpecification(Set processInstanceIds, Set processVariableKeys) { + this.processInstanceIds = processInstanceIds; + this.processVariableKeys = processVariableKeys; + } + + @Override + public Predicate toPredicate( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + Predicate keyAndNameFilter = processVariableKeys + .stream() + .map(processVariableKey -> { + Expression processVariableKeyExpression = root.get(ProcessVariableEntity_.processDefinitionKey); + Expression processVariableValueExpression = root.get(ProcessVariableEntity_.name); + return criteriaBuilder.and( + criteriaBuilder.equal(processVariableKeyExpression, processVariableKey.processDefinitionKey()), + criteriaBuilder.equal(processVariableValueExpression, processVariableKey.variableName()) + ); + }) + .reduce(criteriaBuilder::or) + .orElse(criteriaBuilder.disjunction()); + + return criteriaBuilder.and( + root.get(ProcessVariableEntity_.processInstanceId).in(processInstanceIds), + keyAndNameFilter + ); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/SpecificationSupport.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/SpecificationSupport.java new file mode 100644 index 00000000000..884c031c1d9 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/SpecificationSupport.java @@ -0,0 +1,221 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.SetJoin; +import jakarta.persistence.metamodel.SingularAttribute; +import java.util.Collection; +import java.util.Set; +import java.util.function.Supplier; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.payload.CloudRuntimeEntitySort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +public abstract class SpecificationSupport implements Specification { + + protected void addLikeFilters( + Collection predicates, + Set valuesToFilter, + Root root, + CriteriaBuilder criteriaBuilder, + SingularAttribute attribute + ) { + predicates.add( + valuesToFilter + .stream() + .map(value -> + criteriaBuilder.like(criteriaBuilder.lower(root.get(attribute)), "%" + value.toLowerCase() + "%") + ) + .reduce(criteriaBuilder::or) + .orElse(criteriaBuilder.conjunction()) + ); + } + + protected Predicate[] getProcessVariableValueFilters( + Root root, + Collection filters, + CriteriaBuilder criteriaBuilder + ) { + return filters + .stream() + .map(filter -> + criteriaBuilder.and( + criteriaBuilder.equal( + root.get(ProcessVariableEntity_.processDefinitionKey), + filter.processDefinitionKey() + ), + criteriaBuilder.equal(root.get(ProcessVariableEntity_.name), filter.name()), + getVariableValueCondition(root.get(ProcessVariableEntity_.value), filter, criteriaBuilder) + ) + ) + .toArray(Predicate[]::new); + } + + protected Predicate getHavingClause( + Root root, + Collection filters, + CriteriaBuilder criteriaBuilder + ) { + return filters + .stream() + .map(filter -> + criteriaBuilder.greaterThan( + criteriaBuilder.count( + criteriaBuilder + .selectCase() + .when( + criteriaBuilder.and( + criteriaBuilder.equal( + root.get(ProcessVariableEntity_.processDefinitionKey), + filter.processDefinitionKey() + ), + criteriaBuilder.equal(root.get(ProcessVariableEntity_.name), filter.name()), + getVariableValueCondition( + root.get(ProcessVariableEntity_.value), + filter, + criteriaBuilder + ) + ), + criteriaBuilder.literal(1) + ) + .otherwise(criteriaBuilder.nullLiteral(Long.class)) + ), + 0L + ) + ) + .reduce(criteriaBuilder::and) + .orElse(criteriaBuilder.disjunction()); + } + + protected Predicate getVariableValueCondition( + Path valueColumnPath, + VariableFilter filter, + CriteriaBuilder criteriaBuilder + ) { + VariableValueCondition valueConditionStrategy = + switch (filter.type()) { + case STRING -> new StringVariableValueCondition( + valueColumnPath, + filter.operator(), + filter.value(), + criteriaBuilder + ); + case INTEGER -> new IntegerVariableValueCondition( + valueColumnPath, + filter.operator(), + filter.value(), + criteriaBuilder + ); + case BIGDECIMAL -> new BigDecimalVariableValueCondition( + valueColumnPath, + filter.operator(), + filter.value(), + criteriaBuilder + ); + case DATE -> new DateVariableValueCondition( + valueColumnPath, + filter.operator(), + filter.value(), + criteriaBuilder + ); + case DATETIME -> new DatetimeVariableValueCondition( + valueColumnPath, + filter.operator(), + filter.value(), + criteriaBuilder + ); + case BOOLEAN -> new BooleanVariableValueCondition( + valueColumnPath, + filter.operator(), + filter.value(), + criteriaBuilder + ); + }; + + return valueConditionStrategy.toPredicate(); + } + + protected void applySorting( + Root root, + Supplier> joinSupplier, + CloudRuntimeEntitySort sort, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + if (sort != null) { + validateSort(sort); + Expression orderByClause; + if (sort.isProcessVariable()) { + SetJoin join = joinSupplier.get(); + Expression extractedValue = criteriaBuilder.function( + CustomPostgreSQLDialect.getExtractionFunction(sort.type()), + Object.class, + join.get(ProcessVariableEntity_.value) + ); + orderByClause = + criteriaBuilder + .selectCase() + .when( + criteriaBuilder.and( + criteriaBuilder.equal( + join.get(ProcessVariableEntity_.processDefinitionKey), + sort.processDefinitionKey() + ), + criteriaBuilder.equal(join.get(ProcessVariableEntity_.name), sort.field()) + ), + extractedValue + ) + .otherwise(criteriaBuilder.nullLiteral(Object.class)); + } else { + orderByClause = root.get(sort.field()); + } + if (sort.direction().isAscending()) { + query.orderBy(criteriaBuilder.asc(orderByClause)); + } else { + //This is a workaround to override the nulls first behavior when ordering direction is DESC + query.orderBy(criteriaBuilder.asc(orderByClause.isNull()), criteriaBuilder.desc(orderByClause)); + } + } + } + + protected void validateSort(CloudRuntimeEntitySort sort) { + if (sort.isProcessVariable()) { + if (sort.processDefinitionKey() == null) { + throw new ResponseStatusException( + HttpStatus.BAD_REQUEST, + "Process definition key is required when sorting by process variable" + ); + } + if (sort.type() == null) { + throw new ResponseStatusException( + HttpStatus.BAD_REQUEST, + "Variable type is required when sorting by process variable" + ); + } + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/StringVariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/StringVariableValueCondition.java new file mode 100644 index 00000000000..cd061a1ebaa --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/StringVariableValueCondition.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import org.activiti.cloud.dialect.CustomPostgreSQLDialect; +import org.activiti.cloud.services.query.rest.exception.IllegalFilterException; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableType; + +public class StringVariableValueCondition extends VariableValueCondition { + + public StringVariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + super(path, operator, value, criteriaBuilder); + } + + @Override + protected String getFunctionName() { + return switch (operator) { + case EQUALS -> CustomPostgreSQLDialect.JSON_VALUE_EQUALS; + case LIKE -> CustomPostgreSQLDialect.JSON_VALUE_LIKE_CASE_INSENSITIVE; + default -> throw new IllegalFilterException(VariableType.STRING, operator); + }; + } + + @Override + protected String getConvertedValue() { + return value; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/TaskSpecification.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/TaskSpecification.java new file mode 100644 index 00000000000..7e9223da556 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/TaskSpecification.java @@ -0,0 +1,367 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.SetJoin; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.activiti.cloud.services.query.model.TaskCandidateGroupEntity_; +import org.activiti.cloud.services.query.model.TaskCandidateUserEntity_; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.model.TaskEntity_; +import org.activiti.cloud.services.query.model.TaskVariableEntity; +import org.activiti.cloud.services.query.model.TaskVariableEntity_; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.payload.TaskSearchRequest; +import org.springframework.util.CollectionUtils; + +public class TaskSpecification extends SpecificationSupport { + + List predicates = new ArrayList<>(); + + private final TaskSearchRequest taskSearchRequest; + + private final String userId; + private final Collection userGroups; + + private TaskSpecification(TaskSearchRequest taskSearchRequest, String userId, Collection userGroups) { + this.taskSearchRequest = taskSearchRequest; + this.userId = userId; + this.userGroups = userGroups; + } + + /** + * Creates a specification that retrieve tasks that match filters in the request without restrictions related to any user. + * @param taskSearchRequest the request containing all the filters + * @return a specification that applies the filters in the request + */ + public static TaskSpecification unrestricted(TaskSearchRequest taskSearchRequest) { + return new TaskSpecification(taskSearchRequest, null, null); + } + + /** + * Creates a specification that applies the filters and restricts the retrieved tasks based on the given user and groups. + * In addition to the filters, tasks are retrieved if they match one of the following conditions: + * - user is assignee + * - user is owner + * - user is candidate and task is not assigned + * - any of the user groups is candidate group and task is not assigned + * - there are no candidate users and groups set and task is not assigned + * + * @param taskSearchRequest the request containing all the filters + * @param userId user id to be applied for restriction + * @param userGroups groups to be applied for restriction + * @return a specification that applies the filters and restricts the retrieved tasks based on the given user and groups + */ + public static TaskSpecification restricted( + TaskSearchRequest taskSearchRequest, + String userId, + Collection userGroups + ) { + return new TaskSpecification(taskSearchRequest, userId, userGroups); + } + + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) { + applyUserRestrictionFilter(root, criteriaBuilder); + applyRootTasksFilter(root, criteriaBuilder); + applyStandaloneFilter(root, criteriaBuilder); + applyNameFilter(root, criteriaBuilder); + applyDescriptionFilter(root, criteriaBuilder); + applyProcessDefinitionNameFilter(root, criteriaBuilder); + applyPriorityFilter(root); + applyStatusFilter(root); + applyCompletedByFilter(root); + applyAssigneeFilter(root); + applyCreatedDateFilters(root, criteriaBuilder); + applyLastModifiedDateFilters(root, criteriaBuilder); + applyLastClaimedDateFilters(root, criteriaBuilder); + applyCompletedDateFilters(root, criteriaBuilder); + applyDueDateFilters(root, criteriaBuilder); + applyCandidateUserFilter(root); + applyCandidateGroupFilter(root); + applyTaskVariableFilters(root, query, criteriaBuilder); + applyProcessVariableFilters(root, query, criteriaBuilder); + if (predicates.isEmpty()) { + return criteriaBuilder.conjunction(); + } + return criteriaBuilder.and(predicates.toArray(Predicate[]::new)); + } + + private void applyProcessDefinitionNameFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (!CollectionUtils.isEmpty(taskSearchRequest.processDefinitionName())) { + addLikeFilters( + predicates, + taskSearchRequest.processDefinitionName(), + root, + criteriaBuilder, + TaskEntity_.processDefinitionName + ); + } + } + + private void applyCandidateGroupFilter(Root root) { + if (!CollectionUtils.isEmpty(taskSearchRequest.candidateGroupId())) { + predicates.add( + root + .join(TaskEntity_.taskCandidateGroups) + .get(TaskCandidateGroupEntity_.groupId) + .in(taskSearchRequest.candidateGroupId()) + ); + } + } + + private void applyCandidateUserFilter(Root root) { + if (!CollectionUtils.isEmpty(taskSearchRequest.candidateUserId())) { + predicates.add( + root + .join(TaskEntity_.taskCandidateUsers) + .get(TaskCandidateUserEntity_.userId) + .in(taskSearchRequest.candidateUserId()) + ); + } + } + + private void applyDueDateFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.dueDateFrom() != null) { + predicates.add(criteriaBuilder.greaterThan(root.get(TaskEntity_.dueDate), taskSearchRequest.dueDateFrom())); + } + if (taskSearchRequest.dueDateTo() != null) { + predicates.add(criteriaBuilder.lessThan(root.get(TaskEntity_.dueDate), taskSearchRequest.dueDateTo())); + } + } + + private void applyCompletedDateFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.completedFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan(root.get(TaskEntity_.completedDate), taskSearchRequest.completedFrom()) + ); + } + if (taskSearchRequest.completedTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(TaskEntity_.completedDate), taskSearchRequest.completedTo()) + ); + } + } + + private void applyLastClaimedDateFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.lastClaimedFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan(root.get(TaskEntity_.claimedDate), taskSearchRequest.lastClaimedFrom()) + ); + } + if (taskSearchRequest.lastClaimedTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(TaskEntity_.claimedDate), taskSearchRequest.lastClaimedTo()) + ); + } + } + + private void applyLastModifiedDateFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.lastModifiedFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan(root.get(TaskEntity_.lastModified), taskSearchRequest.lastModifiedFrom()) + ); + } + if (taskSearchRequest.lastModifiedTo() != null) { + predicates.add( + criteriaBuilder.lessThan(root.get(TaskEntity_.lastModified), taskSearchRequest.lastModifiedTo()) + ); + } + } + + private void applyCreatedDateFilters(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.createdFrom() != null) { + predicates.add( + criteriaBuilder.greaterThan(root.get(TaskEntity_.createdDate), taskSearchRequest.createdFrom()) + ); + } + if (taskSearchRequest.createdTo() != null) { + predicates.add(criteriaBuilder.lessThan(root.get(TaskEntity_.createdDate), taskSearchRequest.createdTo())); + } + } + + private void applyAssigneeFilter(Root root) { + if (!CollectionUtils.isEmpty(taskSearchRequest.assignee())) { + predicates.add(root.get(TaskEntity_.assignee).in(taskSearchRequest.assignee())); + } + } + + private void applyCompletedByFilter(Root root) { + if (!CollectionUtils.isEmpty(taskSearchRequest.completedBy())) { + predicates.add(root.get(TaskEntity_.completedBy).in(taskSearchRequest.completedBy())); + } + } + + private void applyStatusFilter(Root root) { + if (!CollectionUtils.isEmpty(taskSearchRequest.status())) { + predicates.add(root.get(TaskEntity_.status).in(taskSearchRequest.status())); + } + } + + private void applyPriorityFilter(Root root) { + if (!CollectionUtils.isEmpty(taskSearchRequest.priority())) { + predicates.add(root.get(TaskEntity_.priority).in(taskSearchRequest.priority())); + } + } + + private void applyDescriptionFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (!CollectionUtils.isEmpty(taskSearchRequest.description())) { + addLikeFilters(predicates, taskSearchRequest.description(), root, criteriaBuilder, TaskEntity_.description); + } + } + + private void applyNameFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (!CollectionUtils.isEmpty(taskSearchRequest.name())) { + addLikeFilters(predicates, taskSearchRequest.name(), root, criteriaBuilder, TaskEntity_.name); + } + } + + private void applyStandaloneFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.onlyStandalone()) { + predicates.add(criteriaBuilder.isNull(root.get(TaskEntity_.processInstanceId))); + } + } + + private void applyRootTasksFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (taskSearchRequest.onlyRoot()) { + predicates.add(criteriaBuilder.isNull(root.get(TaskEntity_.parentTaskId))); + } + } + + private void applyProcessVariableFilters( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + if (!CollectionUtils.isEmpty(taskSearchRequest.processVariableFilters())) { + Root pvRoot = query.from(ProcessVariableEntity.class); + Predicate joinCondition = criteriaBuilder.equal( + root.get(TaskEntity_.processInstanceId), + pvRoot.get(ProcessVariableEntity_.processInstanceId) + ); + + predicates.add( + criteriaBuilder.and( + joinCondition, + criteriaBuilder.or( + getProcessVariableValueFilters( + pvRoot, + taskSearchRequest.processVariableFilters(), + criteriaBuilder + ) + ) + ) + ); + query.groupBy(root.get(TaskEntity_.id)); + query.having(getHavingClause(pvRoot, taskSearchRequest.processVariableFilters(), criteriaBuilder)); + } + } + + private void applyTaskVariableFilters( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + if (!CollectionUtils.isEmpty(taskSearchRequest.taskVariableFilters())) { + SetJoin join = root.join(TaskEntity_.variables); + Predicate[] variableValueFilters = taskSearchRequest + .taskVariableFilters() + .stream() + .map(filter -> + criteriaBuilder.and( + criteriaBuilder.equal(join.get(TaskVariableEntity_.name), filter.name()), + getVariableValueCondition(join.get(TaskVariableEntity_.value), filter, criteriaBuilder) + ) + ) + .toArray(Predicate[]::new); + + predicates.add(criteriaBuilder.or(variableValueFilters)); + query.groupBy(root.get(TaskEntity_.id)); + query.having(getHavingClause(join, taskSearchRequest.taskVariableFilters(), criteriaBuilder)); + } + } + + private void applyUserRestrictionFilter(Root root, CriteriaBuilder criteriaBuilder) { + if (userId != null) { + predicates.add( + criteriaBuilder.or( + criteriaBuilder.equal(root.get(TaskEntity_.assignee), userId), + criteriaBuilder.equal(root.get(TaskEntity_.owner), userId), + criteriaBuilder.and( + criteriaBuilder.isNull(root.get(TaskEntity_.assignee)), + criteriaBuilder.or( + criteriaBuilder.equal( + root + .join(TaskEntity_.taskCandidateUsers, JoinType.LEFT) + .get(TaskCandidateUserEntity_.userId), + userId + ), + root + .join(TaskEntity_.taskCandidateGroups, JoinType.LEFT) + .get(TaskCandidateGroupEntity_.groupId) + .in(userGroups), + criteriaBuilder.and( + criteriaBuilder.isEmpty(root.get(TaskEntity_.taskCandidateUsers)), + criteriaBuilder.isEmpty(root.get(TaskEntity_.taskCandidateGroups)) + ) + ) + ) + ) + ); + } + } + + private Predicate getHavingClause( + SetJoin root, + Collection filters, + CriteriaBuilder criteriaBuilder + ) { + return filters + .stream() + .map(filter -> + criteriaBuilder.greaterThan( + criteriaBuilder.count( + criteriaBuilder + .selectCase() + .when( + criteriaBuilder.and( + criteriaBuilder.equal(root.get(TaskVariableEntity_.name), filter.name()), + getVariableValueCondition( + root.get(TaskVariableEntity_.value), + filter, + criteriaBuilder + ) + ), + criteriaBuilder.literal(1) + ) + .otherwise(criteriaBuilder.nullLiteral(Long.class)) + ), + 0L + ) + ) + .reduce(criteriaBuilder::and) + .orElse(criteriaBuilder.disjunction()); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/VariableValueCondition.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/VariableValueCondition.java new file mode 100644 index 00000000000..9bfd5fc57c1 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/java/org/activiti/cloud/services/query/rest/specification/VariableValueCondition.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Predicate; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; + +public abstract class VariableValueCondition { + + protected final Path path; + protected final FilterOperator operator; + protected final String value; + protected final CriteriaBuilder criteriaBuilder; + + protected VariableValueCondition( + Path path, + FilterOperator operator, + String value, + CriteriaBuilder criteriaBuilder + ) { + this.path = path; + this.operator = operator; + this.value = value; + this.criteriaBuilder = criteriaBuilder; + } + + public Predicate toPredicate() { + return criteriaBuilder.isTrue( + criteriaBuilder.function( + getFunctionName(), + Boolean.class, + path, + criteriaBuilder.literal(getConvertedValue()) + ) + ); + } + + protected abstract String getFunctionName(); + + protected abstract Object getConvertedValue(); +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4017b2543a8..16c3c76b003 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,5 +1,5 @@ -org.activiti.cloud.conf.EventHandlersAutoConfiguration org.activiti.cloud.conf.QueryRestControllersAutoConfiguration org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration +org.activiti.cloud.services.query.rest.config.CustomHibernateAutoConfiguration org.activiti.cloud.services.query.rest.config.QueryRepositoryConfig org.activiti.cloud.services.query.rest.config.QueryRestWebAutoConfiguration diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/query-rest.properties b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/query-rest.properties new file mode 100644 index 00000000000..c65651d76ed --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/main/resources/query-rest.properties @@ -0,0 +1 @@ +logging.level.org.hibernate.collection.spi.AbstractPersistentCollection=ERROR diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/dialect/CustomPostgreSQLDialectIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/dialect/CustomPostgreSQLDialectIT.java new file mode 100644 index 00000000000..b559461df60 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/dialect/CustomPostgreSQLDialectIT.java @@ -0,0 +1,411 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.dialect; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import java.util.Arrays; +import java.util.List; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + properties = { + "spring.main.banner-mode=off", "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@Testcontainers +class CustomPostgreSQLDialectIT { + + @Autowired + VariableRepository variableRepository; + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Autowired + private EntityManager entityManager; + + @AfterEach + void clean() { + variableRepository.deleteAll(); + } + + @Test + void should_findEntity_usingJsonValueEquals_whenVariableIsStringType() { + List variables = createVariablesWithValues("value1", "value2"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_EQUALS, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("value1") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0)); + } + + @Test + void should_findEntity_usingJsonValueEquals_whenVariableIsBooleanType() { + List variables = createVariablesWithValues(true, false); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_EQUALS, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal(true) + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0)); + } + + @Test + void should_findEntity_usingJsonValueLikeCaseSensitive() { + List variables = createVariablesWithValues("value1", "value2", "Value3"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_LIKE_CASE_SENSITIVE, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("value") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactlyInAnyOrder(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueLikeCaseInsensitive() { + List variables = createVariablesWithValues("value1", "Value2", "other"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_LIKE_CASE_INSENSITIVE, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("value") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactlyInAnyOrder(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueNumericEquals() { + List variables = createVariablesWithValues(1, "1.0", 2); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_EQUALS, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal(1) + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueNumericGreaterThan() { + List variables = createVariablesWithValues(1, "1.0", 0.1); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_GREATER_THAN, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal(0.5) + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueNumericGreaterThanEqual() { + List variables = createVariablesWithValues(1, "1.0", 0.1); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_GREATER_THAN_EQUAL, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal(1) + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueNumericLessThan() { + List variables = createVariablesWithValues(1, "1.0", 2); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_LESS_THAN, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal(1.5) + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueNumericLessThanEqual() { + List variables = createVariablesWithValues(1, "1.0", 2); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_LESS_THAN_EQUAL, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal(1) + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_acceptStringArgument_whenTypeIsNumeric() { + List variables = createVariablesWithValues(1.2, 3); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_NUMERIC_EQUALS, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("1.2") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0)); + } + + @Test + void should_findEntity_usingJsonValueDateEquals() { + List variables = createVariablesWithValues("2021-01-01", "2021-01-03"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATE_EQUALS, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2021-01-01") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0)); + } + + @Test + void should_findEntity_usingJsonValueDateGreaterThan() { + List variables = createVariablesWithValues("2021-01-01", "2021-01-02", "2021-01-03"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATE_GREATER_THAN, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2021-01-01") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(1), variables.get(2)); + } + + @Test + void should_findEntity_usingJsonValueDateGreaterThanEqual() { + List variables = createVariablesWithValues("2021-01-01", "2021-01-02", "2021-01-03"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATE_GREATER_THAN_EQUAL, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2021-01-02") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(1), variables.get(2)); + } + + @Test + void should_findEntity_usingJsonValueDateLessThan() { + List variables = createVariablesWithValues("2021-01-01", "2021-01-02", "2021-01-03"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATE_LESS_THAN, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2021-01-03") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueDateLessThanEqual() { + List variables = createVariablesWithValues("2021-01-01", "2021-01-02", "2021-01-03"); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATE_LESS_THAN_EQUAL, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2021-01-02") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueDatetimeEquals() { + List variables = createVariablesWithValues( + "2024-08-02T00:11:00.000+00:00", + "2024-08-02T00:11:35.000+00:00" + ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATETIME_EQUALS, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2024-08-02T00:11:00.000+00:00") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0)); + } + + @Test + void should_findEntity_usingJsonValueDatetimeGreaterThan() { + List variables = createVariablesWithValues( + "2024-08-02T00:11:00.000+00:00", + "2024-08-02T00:11:35.000+00:00" + ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATETIME_GREATER_THAN, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2024-08-02T00:11:00.000+00:00") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(1)); + } + + @Test + void should_findEntity_usingJsonValueDatetimeGreaterThanEqual() { + List variables = createVariablesWithValues( + "2024-08-02T00:11:00.000+00:00", + "2024-08-02T00:11:35.000+00:00", + "2024-08-02T00:11:46.000+00:00" + ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATETIME_GREATER_THAN_EQUAL, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2024-08-02T00:11:35.000+00:00") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(1), variables.get(2)); + } + + @Test + void should_findEntity_usingJsonValueDatetimeLessThan() { + List variables = createVariablesWithValues( + "2024-08-02T00:11:00.000+00:00", + "2024-08-02T00:11:35.000+00:00" + ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATETIME_LESS_THAN, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2024-08-02T00:11:35.000+00:00") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0)); + } + + @Test + void should_findEntity_usingJsonValueDatetimeLessThanEqual() { + List variables = createVariablesWithValues( + "2024-08-02T00:11:00.000+00:00", + "2024-08-02T00:11:35.000+00:00", + "2024-08-02T00:11:46.000+00:00" + ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(); + Expression condition = criteriaBuilder.function( + CustomPostgreSQLDialect.JSON_VALUE_DATETIME_LESS_THAN_EQUAL, + Boolean.class, + query.from(ProcessVariableEntity.class).get(ProcessVariableEntity_.value), + criteriaBuilder.literal("2024-08-02T00:11:35.000+00:00") + ); + query.where(condition); + List resultList = entityManager.createQuery(query).getResultList(); + assertThat(resultList).containsExactly(variables.get(0), variables.get(1)); + } + + private List createVariablesWithValues(Object... values) { + { + return Arrays + .stream(values) + .map(value -> { + ProcessVariableEntity variable = new ProcessVariableEntity(); + variable.setValue(value); + variableRepository.save(variable); + return variable; + }) + .toList(); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandlerTest.java deleted file mode 100644 index 9d4ec0059f5..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ApplicationDeployedEventHandlerTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.test.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.events.ApplicationEvent; -import org.activiti.api.process.model.events.ApplicationEvent.ApplicationEvents; -import org.activiti.api.runtime.model.impl.DeploymentImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudApplicationDeployedEventImpl; -import org.activiti.cloud.services.query.app.repository.ApplicationRepository; -import org.activiti.cloud.services.query.model.ApplicationEntity; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ApplicationDeployedEventHandlerTest { - - private static final String APPLICATION_DEPLOYMENT_NAME = "SpringAutoDeployment"; - - @InjectMocks - private ApplicationDeployedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Mock - private ApplicationRepository applicationRepository; - - @Test - public void handleShouldStoreApplication() { - //given - DeploymentImpl deployment = new DeploymentImpl(); - deployment.setId(UUID.randomUUID().toString()); - deployment.setName(APPLICATION_DEPLOYMENT_NAME); - deployment.setVersion(2); - - CloudApplicationDeployedEventImpl applicationDeployedEvent = new CloudApplicationDeployedEventImpl( - UUID.randomUUID().toString(), - System.currentTimeMillis(), - deployment, - ApplicationEvents.APPLICATION_DEPLOYED - ); - applicationDeployedEvent.setAppName("ApplicationEventName"); - - //when - handler.handle(applicationDeployedEvent); - - //then - ArgumentCaptor applicationCaptor = ArgumentCaptor.forClass(ApplicationEntity.class); - - verify(entityManager).persist(applicationCaptor.capture()); - ApplicationEntity application = applicationCaptor.getValue(); - assertThat(application) - .hasId(deployment.getId()) - .hasName(applicationDeployedEvent.getAppName()) - .hasVersion(deployment.getVersion().toString()); - } - - @Test - public void handleShouldNotStoreApplicationWhenAlreadyExist() { - //given - DeploymentImpl deployment = new DeploymentImpl(); - deployment.setId(UUID.randomUUID().toString()); - deployment.setName(APPLICATION_DEPLOYMENT_NAME); - deployment.setVersion(2); - - CloudApplicationDeployedEventImpl applicationDeployedFirstEvent = new CloudApplicationDeployedEventImpl( - UUID.randomUUID().toString(), - System.currentTimeMillis(), - deployment, - ApplicationEvents.APPLICATION_DEPLOYED - ); - applicationDeployedFirstEvent.setAppName("ApplicationEventName"); - given(applicationRepository.existsByNameAndVersion(any(), any())).willReturn(true); - - //when - handler.handle(applicationDeployedFirstEvent); - - //then - verify(entityManager, never()).persist(any()); - } - - @Test - public void getHandledEventShouldReturnApplicationDeployedEvent() { - String handledEvent = handler.getHandledEvent(); - - Assertions.assertThat(handledEvent).isEqualTo(ApplicationEvent.ApplicationEvents.APPLICATION_DEPLOYED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandlerTest.java deleted file mode 100644 index 43142970683..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/IntegrationErrorReceivedEventHandlerTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.ArrayList; -import java.util.List; -import org.activiti.cloud.api.process.model.CloudIntegrationContext.IntegrationContextStatus; -import org.activiti.cloud.api.process.model.events.CloudIntegrationErrorReceivedEvent; -import org.activiti.cloud.services.query.model.IntegrationContextEntity; -import org.activiti.cloud.services.query.model.ServiceTaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class IntegrationErrorReceivedEventHandlerTest { - - @Captor - private ArgumentCaptor entityManagerPersistCaptor; - - @Mock - private CloudIntegrationErrorReceivedEvent cloudIntegrationEvent; - - @Mock - private ServiceTaskEntity serviceTaskEntity; - - @Mock - private EntityManager entityManager; - - @Test - void handle() { - //given - String errorMessage = "error message"; - int lineNumber = 2137; - String fileName = "exampleFileName"; - String sourceDeclaringClass = "java.lang.Example"; - String sourceMethodName = "doSomething"; - StackTraceElement originalError = new StackTraceElement( - sourceDeclaringClass, - sourceMethodName, - fileName, - lineNumber - ); - - IntegrationContextEntity integrationContext = new IntegrationContextEntity(); - when(cloudIntegrationEvent.getErrorMessage()).thenReturn(errorMessage); - when(cloudIntegrationEvent.getEntity()).thenReturn(integrationContext); - when(cloudIntegrationEvent.getStackTraceElements()).thenReturn(new ArrayList<>(List.of(originalError))); - IntegrationErrorReceivedEventHandler handlerInTest = new IntegrationErrorReceivedEventHandler(entityManager); - when(entityManager.find(IntegrationContextEntity.class, "null:null:null")).thenReturn(integrationContext); - when(entityManager.find(eq(ServiceTaskEntity.class), anyString())).thenReturn(serviceTaskEntity); - - //when - handlerInTest.handle(cloudIntegrationEvent); - - //then - verify(entityManager, times(2)).persist(entityManagerPersistCaptor.capture()); - List allCapturedValues = entityManagerPersistCaptor.getAllValues(); - assertThat(allCapturedValues).hasSize(2); - - IntegrationContextEntity integrationContextEntity = (IntegrationContextEntity) allCapturedValues.get(0); - List stackTraceElements = integrationContextEntity.getStackTraceElements(); - assertThat(stackTraceElements).hasSize(2); - StackTraceElement newStackTraceElement = stackTraceElements.get(0); - assertThat(newStackTraceElement.getLineNumber()).isEqualTo(lineNumber); - assertThat(newStackTraceElement.getFileName()).isEqualTo(fileName); - StackTraceElement sourceStackTraceElement = stackTraceElements.get(1); - assertThat(sourceStackTraceElement.getLineNumber()).isEqualTo(lineNumber); - assertThat(sourceStackTraceElement.getFileName()).isEqualTo(fileName); - assertThat(integrationContextEntity.getStatus()).isEqualTo(IntegrationContextStatus.INTEGRATION_ERROR_RECEIVED); - - ServiceTaskEntity savedServiceTask = (ServiceTaskEntity) allCapturedValues.get(1); - assertThat(savedServiceTask).isEqualTo(serviceTaskEntity); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandlerTest.java deleted file mode 100644 index 9dace67d6ce..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/IntegrationRequestedEventHandlerTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import org.activiti.api.process.model.IntegrationContext; -import org.activiti.api.runtime.model.impl.IntegrationContextImpl; -import org.activiti.cloud.api.process.model.CloudBPMNActivity; -import org.activiti.cloud.api.process.model.events.CloudIntegrationRequestedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudIntegrationRequestedEventImpl; -import org.activiti.cloud.services.query.model.IntegrationContextEntity; -import org.activiti.cloud.services.query.model.ServiceTaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class IntegrationRequestedEventHandlerTest { - - @InjectMocks - private IntegrationRequestedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - void testIntegrationRequestedEventShouldUpdateServiceTaskStatusToStarted() { - //given - CloudIntegrationRequestedEvent event = createIntegrationRequestedEvent(); - String entityId = IntegrationContextEntity.IdBuilderHelper.from(event.getEntity()); - - ServiceTaskEntity serviceTaskEntity = mock(ServiceTaskEntity.class); - IntegrationContextEntity integrationContextEntity = mock(IntegrationContextEntity.class); - - given(entityManager.find(IntegrationContextEntity.class, entityId)).willReturn(integrationContextEntity); - given(entityManager.find(ServiceTaskEntity.class, entityId)).willReturn(serviceTaskEntity); - - //when - handler.handle(event); - - //then - verify(serviceTaskEntity).setStatus(eq(CloudBPMNActivity.BPMNActivityStatus.STARTED)); - verify(serviceTaskEntity).setStartedDate(any(Date.class)); - verify(serviceTaskEntity).setCompletedDate(eq(null)); - - verify(entityManager).persist(integrationContextEntity); - } - - private CloudIntegrationRequestedEvent createIntegrationRequestedEvent() { - IntegrationContext integrationContext = new IntegrationContextImpl() { - { - setClientId("clientId"); - setExecutionId("executionId"); - setProcessInstanceId("processInstanceId"); - } - }; - - return new CloudIntegrationRequestedEventImpl(integrationContext); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandlerTest.java deleted file mode 100644 index c26cebdb10c..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCancelledEventHandlerTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessCancelledEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessCancelledEventHandlerTest { - - @InjectMocks - private ProcessCancelledEventHandler handler; - - @Mock - private EntityManager entityManager; - - /** - * Test that ProcessCancelledEventHandler updates the existing process instance as following: - * - status to CANCELLED - * - lastModified to the event time - */ - @Test - public void testUpdateExistingProcessInstanceWhenCancelled() { - //given - ProcessInstanceEntity processInstanceEntity = mock(ProcessInstanceEntity.class); - given(entityManager.find(ProcessInstanceEntity.class, "200")).willReturn(processInstanceEntity); - - //when - handler.handle(createProcessCancelledEvent("200")); - - //then - verify(entityManager).persist(processInstanceEntity); - verify(processInstanceEntity).setStatus(ProcessInstance.ProcessInstanceStatus.CANCELLED); - verify(processInstanceEntity).setLastModified(any(Date.class)); - } - - private CloudRuntimeEvent createProcessCancelledEvent(String processInstanceId) { - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(processInstanceId); - return new CloudProcessCancelledEventImpl(processInstance); - } - - /** - * Test that ProcessCancelledEventHandler throws QueryException when the related process instance is not found - */ - @Test - public void testThrowExceptionWhenProcessInstanceNotFound() { - //given - given(entityManager.find(ProcessInstanceEntity.class, "200")).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(createProcessCancelledEvent("200"))) - .withMessageContaining("Unable to find process instance with the given id: "); - } - - /** - * Test that ProcessCancelledEventHandler is handling ProcessCancelledEvent events - */ - @Test - public void getHandledEventShouldReturnProcessCancelledEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_CANCELLED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandlerTest.java deleted file mode 100644 index efc401aca76..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterGroupRemovedEventHandlerTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.events.ProcessCandidateStarterGroupEvent; -import org.activiti.api.runtime.model.impl.ProcessCandidateStarterGroupImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessCandidateStarterGroupRemovedEventImpl; -import org.activiti.cloud.services.query.model.ProcessCandidateStarterGroupEntity; -import org.activiti.cloud.services.query.model.ProcessCandidateStarterGroupId; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessCandidateStarterGroupRemovedEventHandlerTest { - - @InjectMocks - private ProcessCandidateStarterGroupRemovedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldRemoveProcessCandidateStarterUser() { - //given - String processDefinitionId = UUID.randomUUID().toString(); - String groupId = UUID.randomUUID().toString(); - ProcessCandidateStarterGroupImpl candidateGroup = new ProcessCandidateStarterGroupImpl( - processDefinitionId, - groupId - ); - - CloudProcessCandidateStarterGroupRemovedEventImpl event = new CloudProcessCandidateStarterGroupRemovedEventImpl( - candidateGroup - ); - - ProcessCandidateStarterGroupEntity processCandidateStarterGroupEntity = new ProcessCandidateStarterGroupEntity( - processDefinitionId, - groupId - ); - - //when - when( - entityManager.find( - ProcessCandidateStarterGroupEntity.class, - new ProcessCandidateStarterGroupId(processDefinitionId, groupId) - ) - ) - .thenReturn(processCandidateStarterGroupEntity); - - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass( - ProcessCandidateStarterGroupEntity.class - ); - verify(entityManager).remove(captor.capture()); - assertThat(captor.getValue().getProcessDefinitionId()).isEqualTo(event.getEntity().getProcessDefinitionId()); - assertThat(captor.getValue().getGroupId()).isEqualTo(event.getEntity().getGroupId()); - } - - @Test - public void getHandledEventShouldReturnProcessCandidateStarterUserRemovedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent) - .isEqualTo( - ProcessCandidateStarterGroupEvent.ProcessCandidateStarterGroupEvents.PROCESS_CANDIDATE_STARTER_GROUP_REMOVED.name() - ); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandlerTest.java deleted file mode 100644 index 3ef9c189bd5..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserAddedEventHandlerTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.events.ProcessCandidateStarterUserEvent; -import org.activiti.api.runtime.model.impl.ProcessCandidateStarterUserImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessCandidateStarterUserAddedEventImpl; -import org.activiti.cloud.services.query.model.ProcessCandidateStarterUserEntity; -import org.activiti.cloud.services.query.model.ProcessCandidateStarterUserId; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessCandidateStarterUserAddedEventHandlerTest { - - @InjectMocks - private ProcessCandidateStarterUserAddedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldStoreNewProcessCandidateStarterUser() { - //given - ProcessCandidateStarterUserImpl candidateUser = new ProcessCandidateStarterUserImpl( - UUID.randomUUID().toString(), - UUID.randomUUID().toString() - ); - CloudProcessCandidateStarterUserAddedEventImpl event = new CloudProcessCandidateStarterUserAddedEventImpl( - candidateUser - ); - - //when - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass( - ProcessCandidateStarterUserEntity.class - ); - verify(entityManager).persist(captor.capture()); - assertThat(captor.getValue().getProcessDefinitionId()).isEqualTo(event.getEntity().getProcessDefinitionId()); - assertThat(captor.getValue().getUserId()).isEqualTo(event.getEntity().getUserId()); - } - - @Test - public void handleShouldNotStoreProcessCandidateStarterUserIfExists() { - //given - ProcessCandidateStarterUserImpl candidateUser = new ProcessCandidateStarterUserImpl( - UUID.randomUUID().toString(), - UUID.randomUUID().toString() - ); - CloudProcessCandidateStarterUserAddedEventImpl event = new CloudProcessCandidateStarterUserAddedEventImpl( - candidateUser - ); - - //when - when( - entityManager.find( - ProcessCandidateStarterUserEntity.class, - new ProcessCandidateStarterUserId(candidateUser.getProcessDefinitionId(), candidateUser.getUserId()) - ) - ) - .thenReturn(new ProcessCandidateStarterUserEntity()); - handler.handle(event); - - //then - verify(entityManager, never()).persist(any()); - } - - @Test - public void getHandledEventShouldReturnProcessCandidateStarterUserAddedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent) - .isEqualTo( - ProcessCandidateStarterUserEvent.ProcessCandidateStarterUserEvents.PROCESS_CANDIDATE_STARTER_USER_ADDED.name() - ); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandlerTest.java deleted file mode 100644 index 51ce267c00d..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCandidateStarterUserRemovedEventHandlerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.events.ProcessCandidateStarterUserEvent; -import org.activiti.api.runtime.model.impl.ProcessCandidateStarterUserImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessCandidateStarterUserRemovedEventImpl; -import org.activiti.cloud.services.query.model.ProcessCandidateStarterUserEntity; -import org.activiti.cloud.services.query.model.ProcessCandidateStarterUserId; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessCandidateStarterUserRemovedEventHandlerTest { - - @InjectMocks - private ProcessCandidateStarterUserRemovedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldRemoveProcessCandidateStarterUser() { - //given - String processDefinitionId = UUID.randomUUID().toString(); - String userId = UUID.randomUUID().toString(); - ProcessCandidateStarterUserImpl candidateUser = new ProcessCandidateStarterUserImpl( - processDefinitionId, - userId - ); - CloudProcessCandidateStarterUserRemovedEventImpl event = new CloudProcessCandidateStarterUserRemovedEventImpl( - candidateUser - ); - - ProcessCandidateStarterUserEntity processCandidateStarterUserEntity = new ProcessCandidateStarterUserEntity( - processDefinitionId, - userId - ); - - //when - when( - entityManager.find( - ProcessCandidateStarterUserEntity.class, - new ProcessCandidateStarterUserId(processDefinitionId, userId) - ) - ) - .thenReturn(processCandidateStarterUserEntity); - - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass( - ProcessCandidateStarterUserEntity.class - ); - verify(entityManager).remove(captor.capture()); - assertThat(captor.getValue().getProcessDefinitionId()).isEqualTo(event.getEntity().getProcessDefinitionId()); - assertThat(captor.getValue().getUserId()).isEqualTo(event.getEntity().getUserId()); - } - - @Test - public void getHandledEventShouldReturnProcessCandidateStarterUserRemovedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent) - .isEqualTo( - ProcessCandidateStarterUserEvent.ProcessCandidateStarterUserEvents.PROCESS_CANDIDATE_STARTER_USER_REMOVED.name() - ); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandlerTest.java deleted file mode 100644 index 1a0a73e0048..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCompletedEventHandlerTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.api.task.model.Task.TaskStatus; -import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; -import org.activiti.cloud.api.process.model.events.CloudProcessCompletedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessCompletedEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.apache.commons.lang3.RandomStringUtils; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class ProcessCompletedEventHandlerTest { - - @InjectMocks - private ProcessCompletedEventHandler handler; - - @Mock - private TaskCancelledEventHandler taskCancelledEventHandler; - - @Mock - private EntityManager entityManager; - - @Captor - private ArgumentCaptor> cancelledEventArgumentCaptor; - - @Test - void handleShouldUpdateCurrentProcessInstanceStateToCompleted() { - //given - CloudProcessCompletedEvent event = createProcessCompletedEvent(); - - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - given(entityManager.find(ProcessInstanceEntity.class, event.getEntity().getId())) - .willReturn(currentProcessInstanceEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity).setStatus(ProcessInstance.ProcessInstanceStatus.COMPLETED); - verify(currentProcessInstanceEntity).setLastModified(any(Date.class)); - } - - private CloudProcessCompletedEvent createProcessCompletedEvent() { - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(UUID.randomUUID().toString()); - return new CloudProcessCompletedEventImpl(processInstance); - } - - @Test - void handleShouldThrowExceptionWhenRelatedProcessInstanceIsNotFound() { - //given - CloudProcessCompletedEvent event = createProcessCompletedEvent(); - given(entityManager.find(ProcessInstanceEntity.class, event.getProcessInstanceId())).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find process instance with the given id: "); - } - - @Test - void getHandledEventShouldReturnProcessCompletedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_COMPLETED.name()); - } - - @Test - void handleShouldUpdateAssignedAndCreatedChildTasksAsCancelled() { - //given - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(UUID.randomUUID().toString()); - CloudProcessCompletedEvent event = new CloudProcessCompletedEventImpl(processInstance); - - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - TaskEntity createdTask = getTaskMock(TaskStatus.CREATED); - TaskEntity assignedTask = getTaskMock(TaskStatus.ASSIGNED); - TaskEntity suspendedTask = getTaskMock(TaskStatus.SUSPENDED); - when(currentProcessInstanceEntity.getTasks()).thenReturn(Set.of(createdTask, assignedTask, suspendedTask)); - given(entityManager.find(ProcessInstanceEntity.class, event.getEntity().getId())) - .willReturn(currentProcessInstanceEntity); - - //when - handler.handle(event); - - //then - verify(currentProcessInstanceEntity).setLastModified(any(Date.class)); - verify(entityManager).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity).setStatus(ProcessInstance.ProcessInstanceStatus.COMPLETED); - - verify(taskCancelledEventHandler, times(2)).handle(cancelledEventArgumentCaptor.capture()); - - List cancelledEntityIDs = cancelledEventArgumentCaptor - .getAllValues() - .stream() - .map(CloudRuntimeEvent::getEntityId) - .collect(Collectors.toList()); - - assertThat(cancelledEntityIDs).containsExactlyInAnyOrder(createdTask.getId(), assignedTask.getId()); - } - - @NotNull - private static TaskEntity getTaskMock(TaskStatus status) { - TaskEntity mockTask = mock(TaskEntity.class); - when(mockTask.getStatus()).thenReturn(status); - lenient().when(mockTask.getId()).thenReturn(RandomStringUtils.random(1)); - return mockTask; - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandlerTest.java deleted file mode 100644 index 3fda69802c7..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessCreatedEventHandlerTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.events.CloudProcessCreatedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessCreatedEventImpl; -import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.test.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessCreatedEventHandlerTest { - - @InjectMocks - private ProcessCreatedEventHandler handler; - - @Mock - private ProcessInstanceRepository processInstanceRepository; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateCurrentProcessInstanceStateToCreated() { - //given - CloudProcessCreatedEvent event = buildProcessCreatedEvent(); - - //when - handler.handle(event); - - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ProcessInstanceEntity.class); - verify(entityManager).persist(argumentCaptor.capture()); - - ProcessInstanceEntity processInstanceEntity = argumentCaptor.getValue(); - Assertions - .assertThat(processInstanceEntity) - .hasId(event.getEntity().getId()) - .hasProcessDefinitionId(event.getEntity().getProcessDefinitionId()) - .hasServiceName(event.getServiceName()) - .hasProcessDefinitionKey(event.getEntity().getProcessDefinitionKey()) - .hasStatus(ProcessInstance.ProcessInstanceStatus.CREATED) - .hasName(event.getEntity().getName()) - .hasProcessDefinitionName(event.getEntity().getProcessDefinitionName()); - } - - private CloudProcessCreatedEvent buildProcessCreatedEvent() { - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(UUID.randomUUID().toString()); - processInstance.setProcessDefinitionId(UUID.randomUUID().toString()); - processInstance.setBusinessKey("myKey"); - processInstance.setName("myName"); - CloudProcessCreatedEventImpl event = new CloudProcessCreatedEventImpl(processInstance); - event.setServiceName("runtime-bundle-a"); - return event; - } - - @Test - public void getHandledEventShouldReturnProcessCreatedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandlerTest.java deleted file mode 100644 index b1f2353771a..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessDeletedEventHandlerTest.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.QueryRestTestApplication; -import org.activiti.api.process.model.ProcessInstance.ProcessInstanceStatus; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; -import org.activiti.cloud.services.query.app.repository.BPMNActivityRepository; -import org.activiti.cloud.services.query.app.repository.BPMNSequenceFlowRepository; -import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; -import org.activiti.cloud.services.query.app.repository.ServiceTaskRepository; -import org.activiti.cloud.services.query.app.repository.TaskRepository; -import org.activiti.cloud.services.query.app.repository.VariableRepository; -import org.activiti.cloud.services.query.model.BPMNActivityEntity; -import org.activiti.cloud.services.query.model.BPMNSequenceFlowEntity; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.ProcessVariableEntity; -import org.activiti.cloud.services.query.model.QBPMNActivityEntity; -import org.activiti.cloud.services.query.model.QBPMNSequenceFlowEntity; -import org.activiti.cloud.services.query.model.QProcessVariableEntity; -import org.activiti.cloud.services.query.model.QServiceTaskEntity; -import org.activiti.cloud.services.query.model.QTaskEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.ServiceTaskEntity; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.TestPropertySource; -import org.springframework.transaction.annotation.Transactional; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = QueryRestTestApplication.class) -@TestPropertySource("classpath:application-test.properties") -@DirtiesContext -class ProcessDeletedEventHandlerTest { - - @Autowired - private ProcessInstanceRepository processInstanceRepository; - - @Autowired - private TaskRepository taskRepository; - - @Autowired - private ServiceTaskRepository serviceTaskRepository; - - @Autowired - private VariableRepository variableRepository; - - @Autowired - private BPMNActivityRepository bpmnActivityRepository; - - @Autowired - private BPMNSequenceFlowRepository bpmnSequenceFlowRepository; - - @Autowired - private EntityManager entityManager; - - private ProcessDeletedEventHandler handler; - - private String completedProcessId; - - private String runningProcessId; - - @BeforeEach - @Transactional - void setUp() { - handler = new ProcessDeletedEventHandler(entityManager); - - completedProcessId = UUID.randomUUID().toString(); - runningProcessId = UUID.randomUUID().toString(); - - insertProcess(completedProcessId, ProcessInstanceStatus.COMPLETED); - insertProcess(runningProcessId, ProcessInstanceStatus.RUNNING); - - assertThat(processInstanceRepository.existsById(completedProcessId)).isTrue(); - assertThat(taskRepository.exists(QTaskEntity.taskEntity.processInstanceId.eq(completedProcessId))).isTrue(); - assertThat( - serviceTaskRepository.exists(QServiceTaskEntity.serviceTaskEntity.processInstanceId.eq(completedProcessId)) - ) - .isTrue(); - assertThat( - variableRepository.exists( - QProcessVariableEntity.processVariableEntity.processInstanceId.eq(completedProcessId) - ) - ) - .isTrue(); - assertThat( - bpmnActivityRepository.exists( - QBPMNActivityEntity.bPMNActivityEntity.processInstanceId.eq(completedProcessId) - ) - ) - .isTrue(); - assertThat( - bpmnSequenceFlowRepository.exists( - QBPMNSequenceFlowEntity.bPMNSequenceFlowEntity.processInstanceId.eq(completedProcessId) - ) - ) - .isTrue(); - - assertThat(processInstanceRepository.existsById(runningProcessId)).isTrue(); - assertThat(taskRepository.exists(QTaskEntity.taskEntity.processInstanceId.eq(runningProcessId))).isTrue(); - assertThat( - serviceTaskRepository.exists(QServiceTaskEntity.serviceTaskEntity.processInstanceId.eq(runningProcessId)) - ) - .isTrue(); - assertThat( - variableRepository.exists( - QProcessVariableEntity.processVariableEntity.processInstanceId.eq(runningProcessId) - ) - ) - .isTrue(); - assertThat( - bpmnActivityRepository.exists(QBPMNActivityEntity.bPMNActivityEntity.processInstanceId.eq(runningProcessId)) - ) - .isTrue(); - assertThat( - bpmnSequenceFlowRepository.exists( - QBPMNSequenceFlowEntity.bPMNSequenceFlowEntity.processInstanceId.eq(runningProcessId) - ) - ) - .isTrue(); - } - - @AfterEach - void cleanUp() { - processInstanceRepository.deleteAll(); - taskRepository.deleteAll(); - serviceTaskRepository.deleteAll(); - variableRepository.deleteAll(); - bpmnActivityRepository.deleteAll(); - bpmnSequenceFlowRepository.deleteAll(); - } - - @Test - @Transactional - void handleShouldDeleteCurrentProcessInstance() { - //given - ProcessInstanceImpl eventProcessInstance = new ProcessInstanceImpl(); - eventProcessInstance.setId(completedProcessId); - CloudProcessDeletedEventImpl event = new CloudProcessDeletedEventImpl(eventProcessInstance); - - //when - handler.handle(event); - - //then - assertThat(processInstanceRepository.existsById(completedProcessId)).isFalse(); - assertThat(taskRepository.exists(QTaskEntity.taskEntity.processInstanceId.eq(completedProcessId))).isFalse(); - assertThat( - serviceTaskRepository.exists(QServiceTaskEntity.serviceTaskEntity.processInstanceId.eq(completedProcessId)) - ) - .isFalse(); - assertThat( - variableRepository.exists( - QProcessVariableEntity.processVariableEntity.processInstanceId.eq(completedProcessId) - ) - ) - .isFalse(); - assertThat( - bpmnActivityRepository.exists( - QBPMNActivityEntity.bPMNActivityEntity.processInstanceId.eq(completedProcessId) - ) - ) - .isFalse(); - assertThat( - bpmnSequenceFlowRepository.exists( - QBPMNSequenceFlowEntity.bPMNSequenceFlowEntity.processInstanceId.eq(completedProcessId) - ) - ) - .isFalse(); - - assertThat(processInstanceRepository.existsById(runningProcessId)).isTrue(); - assertThat(taskRepository.exists(QTaskEntity.taskEntity.processInstanceId.eq(runningProcessId))).isTrue(); - assertThat( - serviceTaskRepository.exists(QServiceTaskEntity.serviceTaskEntity.processInstanceId.eq(runningProcessId)) - ) - .isTrue(); - assertThat( - variableRepository.exists( - QProcessVariableEntity.processVariableEntity.processInstanceId.eq(runningProcessId) - ) - ) - .isTrue(); - assertThat( - bpmnActivityRepository.exists(QBPMNActivityEntity.bPMNActivityEntity.processInstanceId.eq(runningProcessId)) - ) - .isTrue(); - assertThat( - bpmnSequenceFlowRepository.exists( - QBPMNSequenceFlowEntity.bPMNSequenceFlowEntity.processInstanceId.eq(runningProcessId) - ) - ) - .isTrue(); - } - - @Test - void handleShouldThrowExceptionWhenProcessInstanceIsNotCancelledOrCompleted() { - //given - ProcessInstanceImpl eventProcessInstance = new ProcessInstanceImpl(); - eventProcessInstance.setId(runningProcessId); - CloudProcessDeletedEventImpl event = new CloudProcessDeletedEventImpl(eventProcessInstance); - - //then - //when - assertThatExceptionOfType(IllegalStateException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessage( - handler.INVALID_PROCESS_INSTANCE_STATE, - eventProcessInstance.getId(), - ProcessInstanceStatus.RUNNING.name() - ); - - assertThat(processInstanceRepository.existsById(completedProcessId)).isTrue(); - assertThat(processInstanceRepository.existsById(runningProcessId)).isTrue(); - } - - @Test - void handleShouldThrowExceptionWhenRelatedProcessInstanceIsNotFound() { - //given - ProcessInstanceImpl eventProcessInstance = new ProcessInstanceImpl(); - eventProcessInstance.setId("404"); - CloudProcessDeletedEventImpl event = new CloudProcessDeletedEventImpl(eventProcessInstance); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find process instance with the given id: "); - - assertThat(processInstanceRepository.existsById(completedProcessId)).isTrue(); - assertThat(processInstanceRepository.existsById(runningProcessId)).isTrue(); - } - - @Test - void getHandledEventShouldReturnProcessDeletedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED.name()); - } - - private void insertProcess(String id, ProcessInstanceStatus status) { - ProcessInstanceEntity processInstance = buildEntity(id, status); - - processInstance.getTasks().add(buildTaskEntity(UUID.randomUUID().toString(), id + "_Task_A", processInstance)); - processInstance.getTasks().add(buildTaskEntity(UUID.randomUUID().toString(), id + "_Task_B", processInstance)); - - processInstance.getVariables().add(buildProcessVariableEntity(id + "_Var_A", processInstance)); - processInstance.getVariables().add(buildProcessVariableEntity(id + "_Var_B", processInstance)); - processInstance.getVariables().add(buildProcessVariableEntity(id + "_Var_C", processInstance)); - - processInstance - .getActivities() - .add( - buildBPMNActivityEntity( - UUID.randomUUID().toString(), - "MyApp", - "My_Test_Application", - "1", - "MyAppName", - "2", - processInstance - ) - ); - - processInstance - .getServiceTasks() - .add( - buildServiceTaskEntity( - UUID.randomUUID().toString(), - "MyApp", - "My_Test_Application", - "1", - "MyAppName", - "2", - processInstance - ) - ); - - processInstance - .getSequenceFlows() - .add( - buildBPMNSequenceFlowEntity( - UUID.randomUUID().toString(), - "MyApp", - "My_Test_Application", - "1", - "MyAppName", - "2", - processInstance - ) - ); - - processInstanceRepository.save(processInstance); - } - - private ProcessInstanceEntity buildEntity(String id, ProcessInstanceStatus status) { - ProcessInstanceEntity entity = new ProcessInstanceEntity(); - entity.setId(id); - entity.setStatus(status); - return entity; - } - - private TaskEntity buildTaskEntity(String id, String name, ProcessInstanceEntity processInstance) { - TaskEntity taskEntity = new TaskEntity(); - taskEntity.setId(id); - taskEntity.setName(name); - taskEntity.setProcessInstanceId(processInstance.getId()); - return taskRepository.save(taskEntity); - } - - private ProcessVariableEntity buildProcessVariableEntity(String name, ProcessInstanceEntity processInstance) { - ProcessVariableEntity processVariableEntity = new ProcessVariableEntity(); - processVariableEntity.setName(name); - processVariableEntity.setProcessInstanceId(processInstance.getId()); - return variableRepository.save(processVariableEntity); - } - - private BPMNActivityEntity buildBPMNActivityEntity( - String id, - String serviceName, - String serviceFullName, - String serviceVersion, - String appName, - String appVersion, - ProcessInstanceEntity processInstance - ) { - BPMNActivityEntity bpmnActivityEntity = new BPMNActivityEntity( - serviceName, - serviceFullName, - serviceVersion, - appName, - appVersion - ); - bpmnActivityEntity.setId(id); - bpmnActivityEntity.setProcessInstanceId(processInstance.getId()); - return bpmnActivityRepository.save(bpmnActivityEntity); - } - - private ServiceTaskEntity buildServiceTaskEntity( - String id, - String serviceName, - String serviceFullName, - String serviceVersion, - String appName, - String appVersion, - ProcessInstanceEntity processInstance - ) { - ServiceTaskEntity serviceTaskEntity = new ServiceTaskEntity( - serviceName, - serviceFullName, - serviceVersion, - appName, - appVersion - ); - serviceTaskEntity.setId(id); - serviceTaskEntity.setProcessInstanceId(processInstance.getId()); - serviceTaskEntity.setActivityType("serviceTask"); - return serviceTaskRepository.save(serviceTaskEntity); - } - - private BPMNSequenceFlowEntity buildBPMNSequenceFlowEntity( - String id, - String serviceName, - String serviceFullName, - String serviceVersion, - String appName, - String appVersion, - ProcessInstanceEntity processInstance - ) { - BPMNSequenceFlowEntity bpmnSequenceFlowEntity = new BPMNSequenceFlowEntity( - serviceName, - serviceFullName, - serviceVersion, - appName, - appVersion - ); - bpmnSequenceFlowEntity.setId(id); - bpmnSequenceFlowEntity.setProcessInstanceId(processInstance.getId()); - return bpmnSequenceFlowRepository.save(bpmnSequenceFlowEntity); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandlerTest.java deleted file mode 100644 index bfead60c73c..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessDeployedEventHandlerTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.test.Assertions.assertThat; -import static org.mockito.Mockito.*; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.events.ProcessDefinitionEvent; -import org.activiti.api.runtime.model.impl.ProcessDefinitionImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeployedEventImpl; -import org.activiti.cloud.services.query.model.ProcessDefinitionEntity; -import org.activiti.cloud.services.query.model.ProcessModelEntity; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessDeployedEventHandlerTest { - - @InjectMocks - private ProcessDeployedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldStoreProcessDefinitionAndProcessModel() { - //given - ProcessDefinitionImpl eventProcess = new ProcessDefinitionImpl(); - eventProcess.setId(UUID.randomUUID().toString()); - eventProcess.setKey("myProcess"); - eventProcess.setName("My Process"); - eventProcess.setDescription("This is my process description"); - eventProcess.setFormKey("formKey"); - eventProcess.setVersion(2); - - CloudProcessDeployedEventImpl processDeployedEvent = new CloudProcessDeployedEventImpl(eventProcess); - processDeployedEvent.setAppName("myApp"); - processDeployedEvent.setAppVersion("2.1"); - processDeployedEvent.setServiceFullName("my.full.service.name"); - processDeployedEvent.setServiceName("name"); - processDeployedEvent.setServiceType("runtime-bundle"); - processDeployedEvent.setServiceVersion("1.0"); - processDeployedEvent.setProcessModelContent(""); - - //when - handler.handle(processDeployedEvent); - - //then - ArgumentCaptor argumentsCaptor = ArgumentCaptor.forClass(Object.class); - - verify(entityManager, times(2)).merge(argumentsCaptor.capture()); - - ProcessDefinitionEntity storedProcess = (ProcessDefinitionEntity) argumentsCaptor.getAllValues().get(0); - assertThat(storedProcess) - .hasId(eventProcess.getId()) - .hasKey(eventProcess.getKey()) - .hasName(eventProcess.getName()) - .hasDescription(eventProcess.getDescription()) - .hasFormKey(eventProcess.getFormKey()) - .hasVersion(eventProcess.getVersion()) - .hasAppName(processDeployedEvent.getAppName()) - .hasAppVersion(processDeployedEvent.getAppVersion()) - .hasServiceFullName(processDeployedEvent.getServiceFullName()) - .hasServiceName(processDeployedEvent.getServiceName()) - .hasServiceType(processDeployedEvent.getServiceType()) - .hasServiceVersion(processDeployedEvent.getServiceVersion()); - - ProcessModelEntity processModel = (ProcessModelEntity) argumentsCaptor.getAllValues().get(1); - assertThat(processModel).hasProcessModelContent(""); - } - - @Test - public void getHandledEventShouldReturnProcessDeployedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - Assertions - .assertThat(handledEvent) - .isEqualTo(ProcessDefinitionEvent.ProcessDefinitionEvents.PROCESS_DEPLOYED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandlerTest.java deleted file mode 100644 index 31ddf562b8b..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessResumedEventHandlerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.events.CloudProcessResumedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessResumedEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessResumedEventHandlerTest { - - @InjectMocks - private ProcessResumedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateCurrentProcessInstanceStateToRunning() { - //given - ProcessInstanceImpl eventProcessInstance = new ProcessInstanceImpl(); - eventProcessInstance.setId(UUID.randomUUID().toString()); - CloudProcessResumedEvent event = new CloudProcessResumedEventImpl(eventProcessInstance); - - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - given(entityManager.find(ProcessInstanceEntity.class, eventProcessInstance.getId())) - .willReturn(currentProcessInstanceEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity).setStatus(ProcessInstance.ProcessInstanceStatus.RUNNING); - verify(currentProcessInstanceEntity).setLastModified(any(Date.class)); - } - - @Test - public void handleShouldThrowExceptionWhenRelatedProcessInstanceIsNotFound() { - //given - ProcessInstanceImpl eventProcessInstance = new ProcessInstanceImpl(); - eventProcessInstance.setId(UUID.randomUUID().toString()); - CloudProcessResumedEvent event = new CloudProcessResumedEventImpl(eventProcessInstance); - - given(entityManager.find(ProcessInstanceEntity.class, eventProcessInstance.getId())).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find process instance with the given id: "); - } - - @Test - public void getHandledEventShouldReturnProcessResumedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_RESUMED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandlerTest.java deleted file mode 100644 index eabf2ea4f29..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessStartedEventHandlerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.events.CloudProcessStartedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessStartedEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessStartedEventHandlerTest { - - @InjectMocks - private ProcessStartedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateProcessInstanceStatusToRunningAndUpdateInstanceName() { - //given - CloudProcessStartedEvent event = buildProcessStartedEvent(); - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - given(currentProcessInstanceEntity.getStatus()).willReturn(ProcessInstance.ProcessInstanceStatus.CREATED); - given(entityManager.find(ProcessInstanceEntity.class, event.getEntity().getId())) - .willReturn(currentProcessInstanceEntity); - //when - handler.handle(event); - - //then - verify(entityManager).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity).setStatus(ProcessInstance.ProcessInstanceStatus.RUNNING); - verify(currentProcessInstanceEntity).setName(event.getEntity().getName()); - verify(currentProcessInstanceEntity).setStartDate(event.getEntity().getStartDate()); - } - - @Test - public void handleShouldIgnoreEventIfProcessInstanceIsAlreadyInRunningStatus() { - //given - CloudProcessStartedEvent event = buildProcessStartedEvent(); - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - given(currentProcessInstanceEntity.getStatus()).willReturn(ProcessInstance.ProcessInstanceStatus.RUNNING); - given(entityManager.find(ProcessInstanceEntity.class, event.getEntity().getId())) - .willReturn(currentProcessInstanceEntity); - //when - handler.handle(event); - - //then - verify(entityManager, never()).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity, never()).setStatus(ProcessInstance.ProcessInstanceStatus.RUNNING); - } - - private CloudProcessStartedEvent buildProcessStartedEvent() { - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(UUID.randomUUID().toString()); - processInstance.setName("my instance name"); - return new CloudProcessStartedEventImpl(processInstance); - } - - @Test - public void handleShouldThrowExceptionWhenRelatedProcessInstanceIsNotFound() { - //given - CloudProcessStartedEvent event = buildProcessStartedEvent(); - - given(entityManager.find(ProcessInstanceEntity.class, event.getProcessInstanceId())).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find process instance with the given id: "); - } - - @Test - public void getHandledEventShouldReturnProcessStartedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_STARTED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandlerTest.java deleted file mode 100644 index 4275ed4f16c..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessSuspendedEventHandlerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.events.CloudProcessSuspendedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessSuspendedEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessSuspendedEventHandlerTest { - - @InjectMocks - private ProcessSuspendedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateCurrentProcessInstanceStateToSuspended() { - //given - CloudProcessSuspendedEvent event = buildProcessSuspendedEvent(); - - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - given(entityManager.find(ProcessInstanceEntity.class, event.getEntity().getId())) - .willReturn(currentProcessInstanceEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity).setStatus(ProcessInstance.ProcessInstanceStatus.SUSPENDED); - verify(currentProcessInstanceEntity).setLastModified(any(Date.class)); - } - - private CloudProcessSuspendedEvent buildProcessSuspendedEvent() { - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(UUID.randomUUID().toString()); - return new CloudProcessSuspendedEventImpl(processInstance); - } - - @Test - public void handleShouldThrowExceptionWhenRelatedProcessInstanceIsNotFound() { - //given - CloudProcessSuspendedEvent event = buildProcessSuspendedEvent(); - - given(entityManager.find(ProcessInstanceEntity.class, event.getProcessInstanceId())).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find process instance with the given id: "); - } - - @Test - public void getHandledEventShouldReturnProcessSuspendedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_SUSPENDED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandlerTest.java deleted file mode 100644 index 7f53c079560..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessUpdatedEventHandlerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; -import org.activiti.cloud.api.process.model.events.CloudProcessUpdatedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessUpdatedEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.QueryException; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessUpdatedEventHandlerTest { - - @InjectMocks - private ProcessUpdatedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateCurrentProcessInstance() { - //given - CloudProcessUpdatedEvent event = buildProcessUpdatedEvent(); - - ProcessInstanceEntity currentProcessInstanceEntity = mock(ProcessInstanceEntity.class); - given(entityManager.find(ProcessInstanceEntity.class, event.getEntity().getId())) - .willReturn(currentProcessInstanceEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(currentProcessInstanceEntity); - verify(currentProcessInstanceEntity).setBusinessKey(event.getEntity().getBusinessKey()); - verify(currentProcessInstanceEntity).setName(event.getEntity().getName()); - verify(currentProcessInstanceEntity).setLastModified(any(Date.class)); - verifyNoMoreInteractions(currentProcessInstanceEntity); - } - - private CloudProcessUpdatedEventImpl buildProcessUpdatedEvent() { - ProcessInstanceImpl processInstance = new ProcessInstanceImpl(); - processInstance.setId(UUID.randomUUID().toString()); - processInstance.setBusinessKey("businesskey"); - processInstance.setName("name"); - return new CloudProcessUpdatedEventImpl(processInstance); - } - - @Test - public void handleShouldThrowExceptionWhenRelatedProcessInstanceIsNotFound() { - //given - CloudProcessUpdatedEvent event = buildProcessUpdatedEvent(); - String id = event.getEntity().getId(); - - given(entityManager.find(ProcessInstanceEntity.class, id)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find process instance with the given id: "); - } - - @Test - public void getHandledEventShouldReturnProcessUpdatedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(ProcessRuntimeEvent.ProcessEvents.PROCESS_UPDATED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableEntityDeletedHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableEntityDeletedHandlerTest.java deleted file mode 100644 index 90cd79a98d5..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableEntityDeletedHandlerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Optional; -import org.activiti.api.process.model.ProcessInstance.ProcessInstanceStatus; -import org.activiti.api.runtime.model.impl.VariableInstanceImpl; -import org.activiti.cloud.api.model.shared.events.CloudVariableDeletedEvent; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableDeletedEventImpl; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.ProcessVariableEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessVariableEntityDeletedHandlerTest { - - @InjectMocks - private ProcessVariableDeletedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Mock - private EntityManagerFinder entityManagerFinder; - - @Test - public void handleRemoveVariableFromProcessAnDeleteIt() { - //given - CloudVariableDeletedEvent event = buildVariableDeletedEvent(); - - ProcessInstanceEntity processInstanceEntity = new ProcessInstanceEntity(); - processInstanceEntity.setStatus(ProcessInstanceStatus.CREATED); - ProcessVariableEntity variableEntity = new ProcessVariableEntity(); - variableEntity.setName("var"); - processInstanceEntity.getVariables().add(variableEntity); - - given(entityManagerFinder.findProcessInstanceWithVariables("procInstId")) - .willReturn(Optional.of(processInstanceEntity)); - - //when - handler.handle(event); - - //then - verify(entityManager).remove(variableEntity); - assertThat(processInstanceEntity.getVariables()).isEmpty(); - } - - private static CloudVariableDeletedEvent buildVariableDeletedEvent() { - return new CloudVariableDeletedEventImpl( - new VariableInstanceImpl<>("var", "string", "test", "procInstId", null) - ); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableEntityUpdateEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableEntityUpdateEventHandlerTest.java deleted file mode 100644 index 02d331b96cc..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/ProcessVariableEntityUpdateEventHandlerTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; - -import org.activiti.cloud.services.query.model.ProcessVariableEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class ProcessVariableEntityUpdateEventHandlerTest { - - @InjectMocks - private ProcessVariableUpdateEventHandler handler; - - @Mock - private ProcessVariableUpdater variableUpdater; - - @Test - public void handleShouldUpdateVariable() { - //given - ProcessVariableEntity variableEntity = new ProcessVariableEntity(); - variableEntity.setName("var"); - variableEntity.setValue("v1"); - variableEntity.setProcessInstanceId("10"); - - //when - handler.handle(variableEntity); - - //then - verify(variableUpdater).update(eq(variableEntity), anyString()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextIT.java deleted file mode 100644 index 31454e0d4eb..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextIT.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Map; -import org.activiti.api.model.shared.event.VariableEvent; -import org.activiti.api.process.model.events.ApplicationEvent; -import org.activiti.api.process.model.events.BPMNActivityEvent; -import org.activiti.api.process.model.events.IntegrationEvent.IntegrationEvents; -import org.activiti.api.process.model.events.ProcessCandidateStarterGroupEvent; -import org.activiti.api.process.model.events.ProcessCandidateStarterUserEvent; -import org.activiti.api.process.model.events.ProcessDefinitionEvent; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; -import org.activiti.api.process.model.events.SequenceFlowEvent; -import org.activiti.api.task.model.events.TaskCandidateGroupEvent; -import org.activiti.api.task.model.events.TaskCandidateUserEvent; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -public class QueryEventHandlerContextIT { - - @Autowired - private QueryEventHandlerContext context; - - @Test - public void shouldHaveHandlersForAllSupportedEvents() { - //when - Map handlers = context.getHandlers(); - - //then - assertThat(handlers) - .containsOnlyKeys( - ProcessDefinitionEvent.ProcessDefinitionEvents.PROCESS_DEPLOYED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_STARTED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_COMPLETED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_SUSPENDED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_RESUMED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_CANCELLED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_UPDATED.name(), - ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED.name(), - TaskRuntimeEvent.TaskEvents.TASK_CREATED.name(), - TaskRuntimeEvent.TaskEvents.TASK_ASSIGNED.name(), - TaskRuntimeEvent.TaskEvents.TASK_SUSPENDED.name(), - TaskRuntimeEvent.TaskEvents.TASK_ACTIVATED.name(), - TaskRuntimeEvent.TaskEvents.TASK_COMPLETED.name(), - TaskRuntimeEvent.TaskEvents.TASK_CANCELLED.name(), - TaskRuntimeEvent.TaskEvents.TASK_UPDATED.name(), - TaskCandidateUserEvent.TaskCandidateUserEvents.TASK_CANDIDATE_USER_ADDED.name(), - TaskCandidateGroupEvent.TaskCandidateGroupEvents.TASK_CANDIDATE_GROUP_ADDED.name(), - TaskCandidateUserEvent.TaskCandidateUserEvents.TASK_CANDIDATE_USER_REMOVED.name(), - TaskCandidateGroupEvent.TaskCandidateGroupEvents.TASK_CANDIDATE_GROUP_REMOVED.name(), - VariableEvent.VariableEvents.VARIABLE_CREATED.name(), - VariableEvent.VariableEvents.VARIABLE_UPDATED.name(), - VariableEvent.VariableEvents.VARIABLE_DELETED.name(), - BPMNActivityEvent.ActivityEvents.ACTIVITY_STARTED.name(), - BPMNActivityEvent.ActivityEvents.ACTIVITY_COMPLETED.name(), - BPMNActivityEvent.ActivityEvents.ACTIVITY_CANCELLED.name(), - SequenceFlowEvent.SequenceFlowEvents.SEQUENCE_FLOW_TAKEN.name(), - IntegrationEvents.INTEGRATION_REQUESTED.name(), - IntegrationEvents.INTEGRATION_RESULT_RECEIVED.name(), - IntegrationEvents.INTEGRATION_ERROR_RECEIVED.name(), - ApplicationEvent.ApplicationEvents.APPLICATION_DEPLOYED.name(), - ProcessCandidateStarterUserEvent.ProcessCandidateStarterUserEvents.PROCESS_CANDIDATE_STARTER_USER_ADDED.name(), - ProcessCandidateStarterUserEvent.ProcessCandidateStarterUserEvents.PROCESS_CANDIDATE_STARTER_USER_REMOVED.name(), - ProcessCandidateStarterGroupEvent.ProcessCandidateStarterGroupEvents.PROCESS_CANDIDATE_STARTER_GROUP_ADDED.name(), - ProcessCandidateStarterGroupEvent.ProcessCandidateStarterGroupEvents.PROCESS_CANDIDATE_STARTER_GROUP_REMOVED.name() - ); - - assertThat(handlers.get(ProcessDefinitionEvent.ProcessDefinitionEvents.PROCESS_DEPLOYED.name())) - .isInstanceOf(ProcessDeployedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED.name())) - .isInstanceOf(ProcessCreatedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_STARTED.name())) - .isInstanceOf(ProcessStartedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_COMPLETED.name())) - .isInstanceOf(ProcessCompletedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_SUSPENDED.name())) - .isInstanceOf(ProcessSuspendedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_RESUMED.name())) - .isInstanceOf(ProcessResumedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_CANCELLED.name())) - .isInstanceOf(ProcessCancelledEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_UPDATED.name())) - .isInstanceOf(ProcessUpdatedEventHandler.class); - assertThat(handlers.get(ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED.name())) - .isInstanceOf(ProcessDeletedEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_CREATED.name())) - .isInstanceOf(TaskCreatedEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_ASSIGNED.name())) - .isInstanceOf(TaskAssignedEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_SUSPENDED.name())) - .isInstanceOf(TaskSuspendedEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_ACTIVATED.name())) - .isInstanceOf(TaskActivatedEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_COMPLETED.name())) - .isInstanceOf(TaskCompletedEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_CANCELLED.name())) - .isInstanceOf(TaskCancelledEventHandler.class); - assertThat(handlers.get(TaskRuntimeEvent.TaskEvents.TASK_UPDATED.name())) - .isInstanceOf(TaskUpdatedEventHandler.class); - assertThat(handlers.get(TaskCandidateUserEvent.TaskCandidateUserEvents.TASK_CANDIDATE_USER_ADDED.name())) - .isInstanceOf(TaskCandidateUserAddedEventHandler.class); - assertThat(handlers.get(TaskCandidateGroupEvent.TaskCandidateGroupEvents.TASK_CANDIDATE_GROUP_ADDED.name())) - .isInstanceOf(TaskCandidateGroupAddedEventHandler.class); - assertThat(handlers.get(TaskCandidateUserEvent.TaskCandidateUserEvents.TASK_CANDIDATE_USER_REMOVED.name())) - .isInstanceOf(TaskCandidateUserRemovedEventHandler.class); - assertThat(handlers.get(TaskCandidateGroupEvent.TaskCandidateGroupEvents.TASK_CANDIDATE_GROUP_REMOVED.name())) - .isInstanceOf(TaskCandidateGroupRemovedEventHandler.class); - assertThat(handlers.get(VariableEvent.VariableEvents.VARIABLE_CREATED.name())) - .isInstanceOf(VariableCreatedEventHandler.class); - assertThat(handlers.get(VariableEvent.VariableEvents.VARIABLE_UPDATED.name())) - .isInstanceOf(VariableUpdatedEventHandler.class); - assertThat(handlers.get(VariableEvent.VariableEvents.VARIABLE_DELETED.name())) - .isInstanceOf(VariableDeletedEventHandler.class); - assertThat(handlers.get(BPMNActivityEvent.ActivityEvents.ACTIVITY_STARTED.name())) - .isInstanceOf(BPMNActivityStartedEventHandler.class); - assertThat(handlers.get(BPMNActivityEvent.ActivityEvents.ACTIVITY_COMPLETED.name())) - .isInstanceOf(BPMNActivityCompletedEventHandler.class); - assertThat(handlers.get(BPMNActivityEvent.ActivityEvents.ACTIVITY_CANCELLED.name())) - .isInstanceOf(BPMNActivityCancelledEventHandler.class); - assertThat(handlers.get(SequenceFlowEvent.SequenceFlowEvents.SEQUENCE_FLOW_TAKEN.name())) - .isInstanceOf(BPMNSequenceFlowTakenEventHandler.class); - assertThat(handlers.get(IntegrationEvents.INTEGRATION_REQUESTED.name())) - .isInstanceOf(IntegrationRequestedEventHandler.class); - assertThat(handlers.get(IntegrationEvents.INTEGRATION_RESULT_RECEIVED.name())) - .isInstanceOf(IntegrationResultReceivedEventHandler.class); - assertThat(handlers.get(IntegrationEvents.INTEGRATION_ERROR_RECEIVED.name())) - .isInstanceOf(IntegrationErrorReceivedEventHandler.class); - assertThat(handlers.get(ApplicationEvent.ApplicationEvents.APPLICATION_DEPLOYED.name())) - .isInstanceOf(ApplicationDeployedEventHandler.class); - assertThat( - handlers.get( - ProcessCandidateStarterUserEvent.ProcessCandidateStarterUserEvents.PROCESS_CANDIDATE_STARTER_USER_ADDED.name() - ) - ) - .isInstanceOf(ProcessCandidateStarterUserAddedEventHandler.class); - assertThat( - handlers.get( - ProcessCandidateStarterUserEvent.ProcessCandidateStarterUserEvents.PROCESS_CANDIDATE_STARTER_USER_REMOVED.name() - ) - ) - .isInstanceOf(ProcessCandidateStarterUserRemovedEventHandler.class); - assertThat( - handlers.get( - ProcessCandidateStarterGroupEvent.ProcessCandidateStarterGroupEvents.PROCESS_CANDIDATE_STARTER_GROUP_ADDED.name() - ) - ) - .isInstanceOf(ProcessCandidateStarterGroupAddedEventHandler.class); - assertThat( - handlers.get( - ProcessCandidateStarterGroupEvent.ProcessCandidateStarterGroupEvents.PROCESS_CANDIDATE_STARTER_GROUP_REMOVED.name() - ) - ) - .isInstanceOf(ProcessCandidateStarterGroupRemovedEventHandler.class); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizerTest.java deleted file mode 100644 index e6c3be96c40..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextOptimizerTest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; - -import jakarta.persistence.EntityManager; -import java.util.Arrays; -import java.util.List; -import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableCreatedEventImpl; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableDeletedEventImpl; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableUpdatedEventImpl; -import org.activiti.cloud.api.process.model.events.CloudBPMNActivityCancelledEvent; -import org.activiti.cloud.api.process.model.events.CloudBPMNSignalReceivedEvent; -import org.activiti.cloud.api.process.model.events.CloudIntegrationErrorReceivedEvent; -import org.activiti.cloud.api.process.model.impl.events.CloudBPMNActivityCancelledEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudBPMNActivityCompletedEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudBPMNActivityStartedEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudBPMNSignalReceivedEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudIntegrationErrorReceivedEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudIntegrationRequestedEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudIntegrationResultReceivedEventImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudSequenceFlowTakenEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskAssignedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCancelledEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCandidateGroupAddedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCandidateGroupRemovedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCandidateUserAddedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCandidateUserRemovedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCompletedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCreatedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskUpdatedEventImpl; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class QueryEventHandlerContextOptimizerTest { - - @InjectMocks - private QueryEventHandlerContextOptimizer subject; - - @Mock - private EntityManager entityManager; - - @BeforeEach - void setUp() {} - - @Test - void optimizeTaskVariableEvents() { - //given - CloudVariableCreatedEventImpl cloudVariableCreatedEvent = new CloudVariableCreatedEventImpl(); - CloudTaskCreatedEventImpl cloudTaskCreatedEvent = new CloudTaskCreatedEventImpl(); - CloudVariableDeletedEventImpl cloudVariableDeletedEvent = new CloudVariableDeletedEventImpl(); - CloudVariableUpdatedEventImpl cloudVariableUpdatedEvent = new CloudVariableUpdatedEventImpl(); - - List> events = Arrays.asList( - cloudVariableCreatedEvent, - cloudTaskCreatedEvent, - cloudVariableDeletedEvent, - cloudVariableUpdatedEvent - ); - - //when - List> result = subject.optimize(events); - - //then - assertThat(result) - .containsExactly( - cloudTaskCreatedEvent, - cloudVariableCreatedEvent, - cloudVariableUpdatedEvent, - cloudVariableDeletedEvent - ); - } - - @Test - void optimizeTaskCandidateGroupsEvents() { - //given - CloudTaskCreatedEventImpl cloudTaskCreatedEvent = new CloudTaskCreatedEventImpl(); - CloudTaskAssignedEventImpl cloudTaskAssignedEvent = new CloudTaskAssignedEventImpl(); - CloudTaskCompletedEventImpl cloudTaskCompletedEvent = new CloudTaskCompletedEventImpl(); - CloudTaskUpdatedEventImpl cloudTaskUpdatedEvent = new CloudTaskUpdatedEventImpl(); - CloudTaskCancelledEventImpl cloudTaskCancelledEvent = new CloudTaskCancelledEventImpl(); - CloudTaskCandidateUserAddedEventImpl cloudTaskCandidateUserAddedEvent = new CloudTaskCandidateUserAddedEventImpl(); - CloudTaskCandidateGroupAddedEventImpl cloudTaskCandidateGroupAddedEvent = new CloudTaskCandidateGroupAddedEventImpl(); - CloudTaskCandidateUserRemovedEventImpl cloudTaskCandidateUserRemovedEvent = new CloudTaskCandidateUserRemovedEventImpl(); - CloudTaskCandidateGroupRemovedEventImpl cloudTaskCandidateGroupRemovedEvent = new CloudTaskCandidateGroupRemovedEventImpl(); - - List> events = Arrays.asList( - cloudTaskCandidateUserAddedEvent, - cloudTaskCandidateGroupAddedEvent, - cloudTaskCreatedEvent, - cloudTaskAssignedEvent, - cloudTaskUpdatedEvent, - cloudTaskCandidateUserRemovedEvent, - cloudTaskCandidateGroupRemovedEvent, - cloudTaskCompletedEvent, - cloudTaskCancelledEvent - ); - - //when - List> result = subject.optimize(events); - - //then - assertThat(result) - .containsExactly( - cloudTaskCreatedEvent, - cloudTaskCandidateUserAddedEvent, - cloudTaskCandidateGroupAddedEvent, - cloudTaskAssignedEvent, - cloudTaskUpdatedEvent, - cloudTaskCompletedEvent, - cloudTaskCancelledEvent, - cloudTaskCandidateUserRemovedEvent, - cloudTaskCandidateGroupRemovedEvent - ); - } - - @Test - void optimizeServiceTasksEvents() { - //given - CloudIntegrationRequestedEventImpl cloudIntegrationRequestedEvent = new CloudIntegrationRequestedEventImpl(); - CloudIntegrationResultReceivedEventImpl cloudIntegrationResultReceivedEvent = new CloudIntegrationResultReceivedEventImpl(); - CloudIntegrationErrorReceivedEvent cloudIntegrationErrorReceivedEvent = new CloudIntegrationErrorReceivedEventImpl(); - CloudSequenceFlowTakenEventImpl cloudSequenceFlowTakenEvent = new CloudSequenceFlowTakenEventImpl(); - CloudBPMNActivityStartedEventImpl cloudBPMNActivityStartedEvent = new CloudBPMNActivityStartedEventImpl(); - CloudBPMNActivityCompletedEventImpl cloudBPMNActivityCompletedEvent = new CloudBPMNActivityCompletedEventImpl(); - CloudBPMNActivityCancelledEvent cloudBPMNActivityCancelledEvent = new CloudBPMNActivityCancelledEventImpl(); - CloudBPMNSignalReceivedEvent cloudBPMNSignalReceivedEvent = new CloudBPMNSignalReceivedEventImpl(); - - List> events = Arrays.asList( - cloudIntegrationRequestedEvent, - cloudSequenceFlowTakenEvent, - cloudBPMNActivityStartedEvent, - cloudIntegrationResultReceivedEvent, - cloudIntegrationErrorReceivedEvent, - cloudBPMNActivityCompletedEvent, - cloudBPMNActivityCancelledEvent, - cloudBPMNSignalReceivedEvent - ); - - //when - List> result = subject.optimize(events); - - //then - assertThat(result) - .containsExactly( - cloudSequenceFlowTakenEvent, - cloudBPMNActivityStartedEvent, - cloudIntegrationRequestedEvent, - cloudBPMNSignalReceivedEvent, - cloudBPMNActivityCompletedEvent, - cloudBPMNActivityCancelledEvent, - cloudIntegrationResultReceivedEvent, - cloudIntegrationErrorReceivedEvent - ); - } - - @Test - void optimizeEventsByTimestamp() throws InterruptedException { - //given - CloudIntegrationRequestedEventImpl cloudIntegrationRequestedEvent1 = new CloudIntegrationRequestedEventImpl(); - CloudIntegrationResultReceivedEventImpl cloudIntegrationResultReceivedEvent1 = new CloudIntegrationResultReceivedEventImpl(); - CloudIntegrationErrorReceivedEvent cloudIntegrationErrorReceivedEvent1 = new CloudIntegrationErrorReceivedEventImpl(); - CloudSequenceFlowTakenEventImpl cloudSequenceFlowTakenEvent1 = new CloudSequenceFlowTakenEventImpl(); - CloudBPMNActivityStartedEventImpl cloudBPMNActivityStartedEvent1 = new CloudBPMNActivityStartedEventImpl(); - CloudBPMNActivityCompletedEventImpl cloudBPMNActivityCompletedEvent1 = new CloudBPMNActivityCompletedEventImpl(); - CloudBPMNActivityCancelledEvent cloudBPMNActivityCancelledEvent1 = new CloudBPMNActivityCancelledEventImpl(); - CloudBPMNSignalReceivedEvent cloudBPMNSignalReceivedEvent1 = new CloudBPMNSignalReceivedEventImpl(); - - Thread.sleep(10); - - CloudIntegrationRequestedEventImpl cloudIntegrationRequestedEvent2 = new CloudIntegrationRequestedEventImpl(); - CloudIntegrationResultReceivedEventImpl cloudIntegrationResultReceivedEvent2 = new CloudIntegrationResultReceivedEventImpl(); - CloudIntegrationErrorReceivedEvent cloudIntegrationErrorReceivedEvent2 = new CloudIntegrationErrorReceivedEventImpl(); - CloudSequenceFlowTakenEventImpl cloudSequenceFlowTakenEvent2 = new CloudSequenceFlowTakenEventImpl(); - CloudBPMNActivityStartedEventImpl cloudBPMNActivityStartedEvent2 = new CloudBPMNActivityStartedEventImpl(); - CloudBPMNActivityCompletedEventImpl cloudBPMNActivityCompletedEvent2 = new CloudBPMNActivityCompletedEventImpl(); - CloudBPMNActivityCancelledEvent cloudBPMNActivityCancelledEvent2 = new CloudBPMNActivityCancelledEventImpl(); - CloudBPMNSignalReceivedEvent cloudBPMNSignalReceivedEvent2 = new CloudBPMNSignalReceivedEventImpl(); - - List> events = Arrays.asList( - cloudIntegrationRequestedEvent2, - cloudIntegrationRequestedEvent1, - cloudSequenceFlowTakenEvent2, - cloudSequenceFlowTakenEvent1, - cloudBPMNActivityStartedEvent2, - cloudBPMNActivityStartedEvent1, - cloudIntegrationResultReceivedEvent2, - cloudIntegrationResultReceivedEvent1, - cloudIntegrationErrorReceivedEvent2, - cloudIntegrationErrorReceivedEvent1, - cloudBPMNActivityCompletedEvent2, - cloudBPMNActivityCompletedEvent1, - cloudBPMNActivityCancelledEvent2, - cloudBPMNActivityCancelledEvent1, - cloudBPMNSignalReceivedEvent2, - cloudBPMNSignalReceivedEvent1 - ); - - //when - List> result = subject.optimize(events); - - //then - assertThat(result) - .containsExactly( - cloudSequenceFlowTakenEvent1, - cloudSequenceFlowTakenEvent2, - cloudBPMNActivityStartedEvent1, - cloudBPMNActivityStartedEvent2, - cloudIntegrationRequestedEvent1, - cloudIntegrationRequestedEvent2, - cloudBPMNSignalReceivedEvent1, - cloudBPMNSignalReceivedEvent2, - cloudBPMNActivityCompletedEvent1, - cloudBPMNActivityCancelledEvent1, - cloudBPMNActivityCompletedEvent2, - cloudBPMNActivityCancelledEvent2, - cloudIntegrationResultReceivedEvent1, - cloudIntegrationErrorReceivedEvent1, - cloudIntegrationResultReceivedEvent2, - cloudIntegrationErrorReceivedEvent2 - ); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextTest.java deleted file mode 100644 index 86408600437..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/QueryEventHandlerContextTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -import java.util.Collections; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.cloud.api.task.model.events.CloudTaskCompletedEvent; -import org.activiti.cloud.api.task.model.events.CloudTaskCreatedEvent; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCompletedEventImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCreatedEventImpl; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class QueryEventHandlerContextTest { - - private QueryEventHandlerContext context; - - @Mock - private QueryEventHandler handler; - - @BeforeEach - public void setUp() { - doReturn(TaskRuntimeEvent.TaskEvents.TASK_CREATED.name()).when(handler).getHandledEvent(); - context = new QueryEventHandlerContext(Collections.singleton(handler)); - } - - @Test - public void handleShouldSelectHandlerBasedOnEventType() { - //given - CloudTaskCreatedEvent event = new CloudTaskCreatedEventImpl(); - - //when - context.handle(event); - - //then - verify(handler).handle(event); - } - - @Test - public void handleShouldDoNothingWhenNoHandlerIsFoundForTheGivenEvent() { - //given - CloudTaskCompletedEvent event = new CloudTaskCompletedEventImpl(); - - //when - context.handle(event); - - //then - verify(handler, never()).handle(any()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityActivatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityActivatedEventHandlerTest.java deleted file mode 100644 index f50054cb9dc..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityActivatedEventHandlerTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.cloud.services.query.events.handlers.TaskBuilder.aTask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskActivatedEventImpl; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityActivatedEventHandlerTest { - - @InjectMocks - private TaskActivatedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateTaskStatusToCreatedWhenNoAssignee() { - //given - CloudTaskActivatedEventImpl event = buildActivatedEvent(); - - String taskId = event.getEntity().getId(); - TaskEntity taskEntity = aTask().build(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(taskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(taskEntity); - verify(taskEntity).setStatus(Task.TaskStatus.CREATED); - verify(taskEntity).setLastModified(any(Date.class)); - } - - @Test - public void handleShouldUpdateTaskStatusToAssignedWhenHasAssignee() { - //given - CloudTaskActivatedEventImpl event = buildActivatedEvent(); - - String taskId = event.getEntity().getId(); - TaskEntity taskEntity = aTask().withAssignee("user").build(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(taskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(taskEntity); - verify(taskEntity).setStatus(Task.TaskStatus.ASSIGNED); - verify(taskEntity).setLastModified(any(Date.class)); - } - - private CloudTaskActivatedEventImpl buildActivatedEvent() { - return new CloudTaskActivatedEventImpl( - new TaskImpl(UUID.randomUUID().toString(), "my task", Task.TaskStatus.SUSPENDED) - ); - } - - @Test - public void handleShouldThrowExceptionWhenNoTaskIsFoundForTheGivenId() { - //given - CloudTaskActivatedEventImpl event = buildActivatedEvent(); - - String taskId = event.getEntity().getId(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find taskEntity with id: " + taskId); - } - - @Test - public void getHandledEventShouldReturnTaskActivatedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_ACTIVATED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityAssignedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityAssignedEventHandlerTest.java deleted file mode 100644 index a556e191934..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityAssignedEventHandlerTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.cloud.services.query.events.handlers.TaskBuilder.aTask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.events.CloudTaskAssignedEvent; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskAssignedEventImpl; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityAssignedEventHandlerTest { - - @InjectMocks - private TaskAssignedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateTaskStatusToAssigned() { - //given - CloudTaskAssignedEvent event = buildTaskAssignedEvent(); - - String taskId = event.getEntity().getId(); - TaskEntity taskEntity = aTask().build(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(taskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(taskEntity); - verify(taskEntity).setStatus(Task.TaskStatus.ASSIGNED); - verify(taskEntity).setAssignee(event.getEntity().getAssignee()); - verify(taskEntity).setLastModified(any(Date.class)); - } - - private CloudTaskAssignedEvent buildTaskAssignedEvent() { - TaskImpl task = new TaskImpl(UUID.randomUUID().toString(), "task", Task.TaskStatus.ASSIGNED); - task.setAssignee("user"); - return new CloudTaskAssignedEventImpl(task); - } - - @Test - public void handleShouldThrowExceptionWhenNoTaskIsFoundForTheGivenId() { - //given - CloudTaskAssignedEvent event = buildTaskAssignedEvent(); - - String taskId = event.getEntity().getId(); - given(entityManager.find(TaskEntity.class, taskId)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find task with id: " + taskId); - } - - @Test - public void getHandledEventShouldReturnTaskAssignedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_ASSIGNED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCancelledEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCancelledEventHandlerTest.java deleted file mode 100644 index 88cc1598eeb..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCancelledEventHandlerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.cloud.services.query.events.handlers.TaskBuilder.aTask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.events.CloudTaskCancelledEvent; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCancelledEventImpl; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityCancelledEventHandlerTest { - - @InjectMocks - private TaskCancelledEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateTaskStatusToCancelled() { - //given - CloudTaskCancelledEvent event = buildTaskCancelledEvent(); - String taskId = event.getEntity().getId(); - TaskEntity taskEntity = aTask().build(); - given(entityManager.find(TaskEntity.class, taskId)).willReturn(taskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(taskEntity); - verify(taskEntity).setStatus(Task.TaskStatus.CANCELLED); - verify(taskEntity).setLastModified(any(Date.class)); - } - - private CloudTaskCancelledEvent buildTaskCancelledEvent() { - TaskImpl task = new TaskImpl(UUID.randomUUID().toString(), "to be cancelled", Task.TaskStatus.CANCELLED); - return new CloudTaskCancelledEventImpl(task); - } - - @Test - public void handleShouldThrowExceptionWhenTaskNotFound() { - //given - CloudTaskCancelledEvent event = buildTaskCancelledEvent(); - String taskId = event.getEntity().getId(); - given(entityManager.find(TaskEntity.class, taskId)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find task with id: " + taskId); - } - - @Test - public void getHandledEventShouldReturnTaskCancelledEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_CANCELLED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCandidateGroupAddedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCandidateGroupAddedEventHandlerTest.java deleted file mode 100644 index 0c107ae712f..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCandidateGroupAddedEventHandlerTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.task.model.TaskCandidateGroup; -import org.activiti.api.task.model.events.TaskCandidateGroupEvent; -import org.activiti.api.task.model.impl.TaskCandidateGroupImpl; -import org.activiti.cloud.api.task.model.events.CloudTaskCandidateGroupAddedEvent; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCandidateGroupAddedEventImpl; -import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskCandidateGroupEntity; -import org.activiti.cloud.services.query.model.TaskCandidateGroupId; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityCandidateGroupAddedEventHandlerTest { - - @InjectMocks - private TaskCandidateGroupAddedEventHandler handler; - - @Mock - private TaskCandidateGroupRepository taskCandidateRepository; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldStoreNewTaskCandidateGroup() { - //given - CloudTaskCandidateGroupAddedEvent event = buildTaskCandidateGroupAddedEvent(); - //when - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass(TaskCandidateGroupEntity.class); - verify(entityManager).persist(captor.capture()); - assertThat(captor.getValue().getTaskId()).isEqualTo(event.getEntity().getTaskId()); - assertThat(captor.getValue().getGroupId()).isEqualTo(event.getEntity().getGroupId()); - } - - @Test - public void handleShouldNotStoreTaskCandidateGroupIfExists() { - //given - CloudTaskCandidateGroupAddedEvent event = buildTaskCandidateGroupAddedEvent(); - TaskCandidateGroup entity = event.getEntity(); - - //when - when( - entityManager.find( - TaskCandidateGroupEntity.class, - new TaskCandidateGroupId(entity.getTaskId(), entity.getGroupId()) - ) - ) - .thenReturn(new TaskCandidateGroupEntity()); - handler.handle(event); - - //then - verify(entityManager, never()).persist(any()); - } - - @Test - public void handleShouldThrowExceptionWhenUnableToSave() { - //given - CloudTaskCandidateGroupAddedEvent event = buildTaskCandidateGroupAddedEvent(); - Exception cause = new RuntimeException("Something went wrong"); - doThrow(cause).when(entityManager).persist(any(TaskCandidateGroupEntity.class)); - - //when - Throwable throwable = catchThrowable(() -> handler.handle(event)); - - //then - assertThat(throwable) - .isInstanceOf(QueryException.class) - .hasCause(cause) - .hasMessageContaining("Error handling TaskCandidateGroupAddedEvent["); - } - - private CloudTaskCandidateGroupAddedEvent buildTaskCandidateGroupAddedEvent() { - return new CloudTaskCandidateGroupAddedEventImpl( - new TaskCandidateGroupImpl(UUID.randomUUID().toString(), UUID.randomUUID().toString()) - ); - } - - @Test - public void getHandledEventShouldReturnTaskCandidateGroupAddedEvent() { - //when - String event = handler.getHandledEvent(); - - //then - assertThat(event).isEqualTo(TaskCandidateGroupEvent.TaskCandidateGroupEvents.TASK_CANDIDATE_GROUP_ADDED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCandidateUserAddedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCandidateUserAddedEventHandlerTest.java deleted file mode 100644 index 15a8837f783..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCandidateUserAddedEventHandlerTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.UUID; -import org.activiti.api.task.model.events.TaskCandidateUserEvent; -import org.activiti.api.task.model.impl.TaskCandidateUserImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCandidateUserAddedEventImpl; -import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; -import org.activiti.cloud.services.query.model.TaskCandidateUserId; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityCandidateUserAddedEventHandlerTest { - - @InjectMocks - private TaskCandidateUserAddedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldStoreNewTaskCandidateUser() { - //given - TaskCandidateUserImpl candidateUser = new TaskCandidateUserImpl( - UUID.randomUUID().toString(), - UUID.randomUUID().toString() - ); - CloudTaskCandidateUserAddedEventImpl event = new CloudTaskCandidateUserAddedEventImpl(candidateUser); - - //when - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass(TaskCandidateUserEntity.class); - verify(entityManager).persist(captor.capture()); - assertThat(captor.getValue().getTaskId()).isEqualTo(event.getEntity().getTaskId()); - assertThat(captor.getValue().getUserId()).isEqualTo(event.getEntity().getUserId()); - } - - @Test - public void handleShouldNotStoreTaskCandidateUserIfExists() { - //given - TaskCandidateUserImpl candidateUser = new TaskCandidateUserImpl( - UUID.randomUUID().toString(), - UUID.randomUUID().toString() - ); - CloudTaskCandidateUserAddedEventImpl event = new CloudTaskCandidateUserAddedEventImpl(candidateUser); - - //when - when( - entityManager.find( - TaskCandidateUserEntity.class, - new TaskCandidateUserId(candidateUser.getTaskId(), candidateUser.getUserId()) - ) - ) - .thenReturn(new TaskCandidateUserEntity()); - handler.handle(event); - - //then - verify(entityManager, never()).persist(any()); - } - - @Test - public void getHandledEventShouldReturnTaskCandidateUserEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent) - .isEqualTo(TaskCandidateUserEvent.TaskCandidateUserEvents.TASK_CANDIDATE_USER_ADDED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCompletedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCompletedEventHandlerTest.java deleted file mode 100644 index e76ba0d6def..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCompletedEventHandlerTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.cloud.services.query.events.handlers.TaskBuilder.aTask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCompletedEventImpl; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityCompletedEventHandlerTest { - - @InjectMocks - private TaskCompletedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateTaskStatusToCompleted() { - //given - CloudTaskCompletedEventImpl event = buildTaskCompletedEvent(); - String taskId = event.getEntity().getId(); - TaskEntity eventTaskEntity = aTask() - .withCreatedDate(new Date(System.currentTimeMillis() - 86400000L)) - .withCompletedDate(new Date()) - .build(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(eventTaskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(eventTaskEntity); - verify(eventTaskEntity).setStatus(Task.TaskStatus.COMPLETED); - verify(eventTaskEntity).setLastModified(any(Date.class)); - } - - private CloudTaskCompletedEventImpl buildTaskCompletedEvent() { - return new CloudTaskCompletedEventImpl( - new TaskImpl(UUID.randomUUID().toString(), "my task", Task.TaskStatus.COMPLETED) - ); - } - - @Test - public void handleShouldThrowAnExceptionWhenNoTaskIsFoundForTheGivenId() { - //given - CloudTaskCompletedEventImpl event = buildTaskCompletedEvent(); - String taskId = event.getEntity().getId(); - given(entityManager.find(TaskEntity.class, taskId)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find task with id: " + taskId); - } - - @Test - public void getHandledEventShouldReturnTaskCompletedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_COMPLETED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCreatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCreatedEventHandlerTest.java deleted file mode 100644 index 158239f3ab2..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityCreatedEventHandlerTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.LinkedHashSet; -import java.util.Optional; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskCreatedEventImpl; -import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; -import org.activiti.cloud.services.query.app.repository.TaskRepository; -import org.activiti.cloud.services.query.model.ProcessInstanceEntity; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityCreatedEventHandlerTest { - - @InjectMocks - private TaskCreatedEventHandler handler; - - @Mock - private TaskRepository taskRepository; - - @Mock - private EntityManager entityManager; - - @Mock - private EntityManagerFinder entityManagerFinder; - - @Mock - private ProcessInstanceRepository processInstanceRepository; - - @Test - public void handleShouldStoreNewTaskInstance() { - //given - ProcessInstanceEntity processInstanceEntity = mock(ProcessInstanceEntity.class); - when(processInstanceEntity.getProcessDefinitionName()).thenReturn("processDefinitionName"); - when(processInstanceEntity.getTasks()).thenReturn(new LinkedHashSet<>()); - - TaskImpl task = new TaskImpl(UUID.randomUUID().toString(), "task", Task.TaskStatus.CREATED); - task.setCreatedDate(new Date()); - task.setProcessInstanceId(UUID.randomUUID().toString()); - task.setProcessDefinitionId("processDefinitionId"); - task.setTaskDefinitionKey("taskDefinitionKey"); - - CloudTaskCreatedEventImpl event = new CloudTaskCreatedEventImpl(task); - event.setServiceName("runtime-bundle-a"); - event.setProcessDefinitionVersion(10); - event.setBusinessKey("businessKey"); - - when(entityManagerFinder.findProcessInstanceWithTasks(task.getProcessInstanceId())) - .thenReturn(Optional.of(processInstanceEntity)); - - //when - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass(TaskEntity.class); - verify(entityManager).persist(captor.capture()); - assertThat(captor.getValue().getStatus()).isEqualTo(Task.TaskStatus.CREATED); - assertThat(captor.getValue().getLastModified()).isNotNull(); - assertThat(captor.getValue().getProcessInstance()).isEqualTo(processInstanceEntity); - assertThat(captor.getValue().getServiceName()).isEqualTo(event.getServiceName()); - assertThat(captor.getValue().getProcessInstanceId()).isEqualTo(task.getProcessInstanceId()); - assertThat(captor.getValue().getProcessDefinitionId()).isEqualTo(task.getProcessDefinitionId()); - assertThat(captor.getValue().getProcessDefinitionVersion()).isEqualTo(event.getProcessDefinitionVersion()); - assertThat(captor.getValue().getBusinessKey()).isEqualTo(event.getBusinessKey()); - assertThat(captor.getValue().getTaskDefinitionKey()).isEqualTo(task.getTaskDefinitionKey()); - assertThat(captor.getValue().getProcessDefinitionName()).isEqualTo("processDefinitionName"); - assertThat(processInstanceEntity.getTasks()).containsOnly(captor.getValue()); - } - - @Test - public void getHandledEventShouldReturnTaskCreatedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_CREATED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntitySuspendedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntitySuspendedEventHandlerTest.java deleted file mode 100644 index ddac711fe09..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntitySuspendedEventHandlerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.cloud.services.query.events.handlers.TaskBuilder.aTask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskSuspendedEventImpl; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntitySuspendedEventHandlerTest { - - @InjectMocks - private TaskSuspendedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateTaskStatusToSuspended() { - //given - CloudTaskSuspendedEventImpl event = buildTaskSuspendedEvent(); - String taskId = event.getEntity().getId(); - TaskEntity taskEntity = aTask().build(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(taskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(taskEntity); - verify(taskEntity).setStatus(Task.TaskStatus.SUSPENDED); - verify(taskEntity).setLastModified(any(Date.class)); - } - - private CloudTaskSuspendedEventImpl buildTaskSuspendedEvent() { - return new CloudTaskSuspendedEventImpl( - new TaskImpl(UUID.randomUUID().toString(), "task", Task.TaskStatus.SUSPENDED) - ); - } - - @Test - public void handleShouldThrowExceptionWhenNoTaskIsFoundForTheGivenId() { - //given - CloudTaskSuspendedEventImpl event = buildTaskSuspendedEvent(); - String taskId = event.getEntity().getId(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find task with id: " + taskId); - } - - @Test - public void getHandledEventShouldReturnTaskSuspendedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_SUSPENDED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityUpdatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityUpdatedEventHandlerTest.java deleted file mode 100644 index 92db9bd0327..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityUpdatedEventHandlerTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.activiti.cloud.services.query.events.handlers.TaskBuilder.aTask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import jakarta.persistence.EntityManager; -import java.util.Date; -import java.util.UUID; -import org.activiti.api.task.model.Task; -import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.model.impl.TaskImpl; -import org.activiti.cloud.api.task.model.events.CloudTaskUpdatedEvent; -import org.activiti.cloud.api.task.model.impl.events.CloudTaskUpdatedEventImpl; -import org.activiti.cloud.services.query.model.QueryException; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityUpdatedEventHandlerTest { - - @InjectMocks - private TaskUpdatedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Test - public void handleShouldUpdateTask() { - //given - CloudTaskUpdatedEvent event = buildTaskUpdateEvent(); - String taskId = event.getEntity().getId(); - TaskEntity eventTaskEntity = aTask().build(); - - given(entityManager.find(TaskEntity.class, taskId)).willReturn(eventTaskEntity); - - //when - handler.handle(event); - - //then - verify(entityManager).persist(eventTaskEntity); - verify(eventTaskEntity).setName(event.getEntity().getName()); - verify(eventTaskEntity).setDescription(event.getEntity().getDescription()); - verify(eventTaskEntity).setPriority(event.getEntity().getPriority()); - verify(eventTaskEntity).setDueDate(event.getEntity().getDueDate()); - verify(eventTaskEntity).setFormKey(event.getEntity().getFormKey()); - verify(eventTaskEntity).setParentTaskId(event.getEntity().getParentTaskId()); - verify(eventTaskEntity).setLastModified(any(Date.class)); - verify(eventTaskEntity).setStatus(event.getEntity().getStatus()); - - verifyNoMoreInteractions(eventTaskEntity); - } - - private CloudTaskUpdatedEventImpl buildTaskUpdateEvent() { - final TaskImpl task = new TaskImpl(UUID.randomUUID().toString(), "my task", Task.TaskStatus.ASSIGNED); - task.setAssignee("user"); - task.setDescription("task description"); - task.setPriority(75); - task.setDueDate(new Date()); - return new CloudTaskUpdatedEventImpl(task); - } - - @Test - public void handleShouldThrowAnExceptionWhenNoTaskIsFoundForTheGivenId() { - //given - CloudTaskUpdatedEventImpl event = buildTaskUpdateEvent(); - String taskId = event.getEntity().getId(); - given(entityManager.find(TaskEntity.class, taskId)).willReturn(null); - - //then - //when - assertThatExceptionOfType(QueryException.class) - .isThrownBy(() -> handler.handle(event)) - .withMessageContaining("Unable to find task with id: " + taskId); - } - - @Test - public void getHandledEventShouldReturnTaskUpdatedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(TaskRuntimeEvent.TaskEvents.TASK_UPDATED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityVariableEntityDeletedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityVariableEntityDeletedEventHandlerTest.java deleted file mode 100644 index 935e3160820..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityVariableEntityDeletedEventHandlerTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityManager; -import java.util.Optional; -import org.activiti.api.runtime.model.impl.VariableInstanceImpl; -import org.activiti.api.task.model.Task.TaskStatus; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableDeletedEventImpl; -import org.activiti.cloud.services.query.model.TaskEntity; -import org.activiti.cloud.services.query.model.TaskVariableEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityVariableEntityDeletedEventHandlerTest { - - @InjectMocks - private TaskVariableDeletedEventHandler handler; - - @Mock - private EntityManager entityManager; - - @Mock - private EntityManagerFinder entityManagerFinder; - - @Test - public void handleShouldDeleteIt() { - //given - VariableInstanceImpl variableInstance = new VariableInstanceImpl<>( - "var", - "string", - "v1", - "procInstId", - "taskId" - ); - CloudVariableDeletedEventImpl event = new CloudVariableDeletedEventImpl(variableInstance); - - TaskVariableEntity variableEntity = new TaskVariableEntity(); - variableEntity.setName("var"); - TaskEntity taskEntity = new TaskEntity(); - taskEntity.setStatus(TaskStatus.CREATED); - taskEntity.getVariables().add(variableEntity); - - when(entityManagerFinder.findTaskWithVariables("taskId")).thenReturn(Optional.of(taskEntity)); - - //when - handler.handle(event); - - //then - verify(entityManager).remove(variableEntity); - assertThat(taskEntity.getVariables()).isEmpty(); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityVariableEntityUpdatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityVariableEntityUpdatedEventHandlerTest.java deleted file mode 100644 index 11daada06a6..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/TaskEntityVariableEntityUpdatedEventHandlerTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; - -import org.activiti.cloud.services.query.model.TaskVariableEntity; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class TaskEntityVariableEntityUpdatedEventHandlerTest { - - @InjectMocks - private TaskVariableUpdatedEventHandler handler; - - @Mock - private TaskVariableUpdater variableUpdater; - - @Test - public void handleShouldUpdateVariableValue() { - //given - String taskId = "10"; - TaskVariableEntity updatedVariableEntity = new TaskVariableEntity(); - updatedVariableEntity.setName("var"); - updatedVariableEntity.setType("string"); - updatedVariableEntity.setValue("content"); - updatedVariableEntity.setTaskId(taskId); - - //when - handler.handle(updatedVariableEntity); - - //then - verify(variableUpdater).update(eq(updatedVariableEntity), anyString()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityDeletedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityDeletedEventHandlerTest.java deleted file mode 100644 index 42092428d03..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityDeletedEventHandlerTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; - -import org.activiti.api.model.shared.event.VariableEvent; -import org.activiti.api.runtime.model.impl.VariableInstanceImpl; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableDeletedEventImpl; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class VariableEntityDeletedEventHandlerTest { - - @InjectMocks - private VariableDeletedEventHandler handler; - - @Mock - private ProcessVariableDeletedEventHandler processVariableDeletedHandler; - - @Mock - private TaskVariableDeletedEventHandler taskVariableDeletedEventHandler; - - @Test - public void handleShouldUseProcessVariableDeleteHandlerWhenNoTaskId() { - //given - CloudVariableDeletedEventImpl event = new CloudVariableDeletedEventImpl(buildVariable()); - - //when - handler.handle(event); - - //then - verify(processVariableDeletedHandler).handle(event); - } - - private static VariableInstanceImpl buildVariable() { - return new VariableInstanceImpl<>("var", "v1", "string", "procInstId", null); - } - - @Test - public void handleShouldUseProcessVariableDeleteHandlerWhenTaskIdIsPresent() { - //given - CloudVariableDeletedEventImpl event = new CloudVariableDeletedEventImpl(buildVariableWithTaskId()); - - //when - handler.handle(event); - - //then - verify(taskVariableDeletedEventHandler).handle(event); - } - - private static VariableInstanceImpl buildVariableWithTaskId() { - return new VariableInstanceImpl<>("var", "v1", "string", "procInstId", "taskId"); - } - - @Test - public void getHandledEventShouldReturnVariableDeletedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(VariableEvent.VariableEvents.VARIABLE_DELETED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdatedEventHandlerTest.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdatedEventHandlerTest.java deleted file mode 100644 index 772d003ac52..00000000000 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/events/handlers/VariableEntityUpdatedEventHandlerTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2017-2020 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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.activiti.cloud.services.query.events.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; - -import org.activiti.api.model.shared.event.VariableEvent; -import org.activiti.api.runtime.model.impl.VariableInstanceImpl; -import org.activiti.cloud.api.model.shared.impl.events.CloudVariableUpdatedEventImpl; -import org.activiti.cloud.services.query.model.ProcessVariableEntity; -import org.activiti.cloud.services.query.model.TaskVariableEntity; -import org.activiti.test.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class VariableEntityUpdatedEventHandlerTest { - - @InjectMocks - private VariableUpdatedEventHandler handler; - - @Mock - private ProcessVariableUpdateEventHandler processVariableUpdateEventHandler; - - @Mock - private TaskVariableUpdatedEventHandler taskVariableUpdatedEventHandler; - - @Test - public void handleShouldUseProcessVariableUpdateHandlerWhenNoTaskId() { - //given - CloudVariableUpdatedEventImpl event = new CloudVariableUpdatedEventImpl<>(buildVariable(), "v0"); - event.setServiceName("runtime-bundle-a"); - - //when - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass(ProcessVariableEntity.class); - verify(processVariableUpdateEventHandler).handle(captor.capture()); - - ProcessVariableEntity variableEntity = captor.getValue(); - Assertions - .assertThat(variableEntity) - .hasProcessInstanceId(event.getEntity().getProcessInstanceId()) - .hasName("var") - .hasServiceName("runtime-bundle-a") - .hasValue("v1") - .hasType("string"); - } - - private static VariableInstanceImpl buildVariable() { - return new VariableInstanceImpl<>("var", "string", "v1", "10", null); - } - - @Test - public void handleShouldUseTaskVariableUpdateHandlerWhenTaskIdIsSet() { - //given - CloudVariableUpdatedEventImpl event = new CloudVariableUpdatedEventImpl<>( - buildVariableWithTaskId(), - "v0" - ); - event.setServiceName("runtime-bundle-a"); - - //when - handler.handle(event); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass(TaskVariableEntity.class); - verify(taskVariableUpdatedEventHandler).handle(captor.capture()); - - TaskVariableEntity variableEntity = captor.getValue(); - Assertions - .assertThat(variableEntity) - .hasTaskId("20") - .hasName("var") - .hasValue("v1") - .hasServiceName("runtime-bundle-a") - .hasType("string"); - } - - private static VariableInstanceImpl buildVariableWithTaskId() { - return new VariableInstanceImpl<>("var", "string", "v1", "10", "20"); - } - - @Test - public void getHandledEventClassShouldReturnVariableUpdatedEvent() { - //when - String handledEvent = handler.getHandledEvent(); - - //then - assertThat(handledEvent).isEqualTo(VariableEvent.VariableEvents.VARIABLE_UPDATED.name()); - } -} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/AbstractProcessInstanceEntitySearchControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/AbstractProcessInstanceEntitySearchControllerIT.java new file mode 100644 index 00000000000..f7a01438484 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/AbstractProcessInstanceEntitySearchControllerIT.java @@ -0,0 +1,2326 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.postProcessors; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.webAppContextSetup; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInRelativeOrder; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import java.math.BigDecimal; +import java.util.Date; +import org.activiti.QueryRestTestApplication; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.activiti.cloud.services.query.rest.payload.CloudRuntimeEntitySort; +import org.activiti.cloud.services.query.util.ProcessInstanceSearchRequestBuilder; +import org.activiti.cloud.services.query.util.QueryTestUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.context.WebApplicationContext; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +@ContextConfiguration(classes = { QueryRestTestApplication.class, AlfrescoWebAutoConfiguration.class }) +abstract class AbstractProcessInstanceEntitySearchControllerIT { + + private static final String PROCESS_DEFINITION_KEY = "process-def-key"; + + public static final String USER = "testuser"; + + @Autowired + private WebApplicationContext context; + + @Autowired + protected QueryTestUtils queryTestUtils; + + protected final String processInstanceJsonPath = "_embedded.processInstances"; + protected final String processInstanceIdJsonPath = "_embedded.processInstances.id"; + + @BeforeEach + void setUp() { + webAppContextSetup(context); + postProcessors(csrf().asHeader()); + } + + @AfterEach + void cleanUp() { + queryTestUtils.cleanUp(); + } + + protected abstract String getSearchEndpoint(); + + @Test + void should_returnProcessInstances_filteredByNameLike() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withName("Beautiful process instance name") + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withName("Amazing process instance name") + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withName("Ugly process instance name").buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withNames("amazing", "beautiful"); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByAppVersion() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withAppVersion("1.0.0") + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withAppVersion("2.0.0") + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withAppVersion("3.0.0").buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withAppVersions("1.0.0", "2.0.0"); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByLastModifiedFrom() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withLastModified(new Date(2000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withLastModified(new Date(1000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withLastModifiedFrom(new Date(1000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByLastModifiedTo() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withLastModified(new Date(1000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withLastModified(new Date(2000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withLastModifiedTo(new Date(2000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByStartFrom() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withStartDate(new Date(2000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withStartDate(new Date(1000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withStartFrom(new Date(1000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByStartTo() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withStartDate(new Date(1000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withStartDate(new Date(2000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withStartTo(new Date(2000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByCompletedFrom() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withCompletedDate(new Date(2000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withCompletedDate(new Date(1000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withCompletedFrom(new Date(1000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByCompletedTo() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withCompletedDate(new Date(1000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withCompletedDate(new Date(2000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withCompletedTo(new Date(2000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredBySuspendedFrom() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withSuspendedDate(new Date(2000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withSuspendedDate(new Date(1000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSuspendedFrom(new Date(1000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredBySuspendedTo() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withSuspendedDate(new Date(1000)) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator(USER).withSuspendedDate(new Date(2000)).buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSuspendedTo(new Date(2000)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstance_withoutProcessVariables() { + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .buildAndSave(); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body("{}") + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance.getId())) + .body(processInstanceJsonPath + "[0].variables", empty()); + } + + @Test + void should_returnProcessInstances_withJustRequestedProcessVariables() { + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.INTEGER, 1), + new QueryTestUtils.VariableInput("var3", VariableType.STRING, "value3"), + new QueryTestUtils.VariableInput("var4", VariableType.BOOLEAN, true) + ) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableKeys( + new ProcessVariableKey(PROCESS_DEFINITION_KEY, "var1"), + new ProcessVariableKey(PROCESS_DEFINITION_KEY, "var3") + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance.getId())) + .body(processInstanceJsonPath + "[0].variables", hasSize(2)) + .body(processInstanceJsonPath + "[0].variables.name", hasItem("var1")) + .body(processInstanceJsonPath + "[0].variables.name", hasItem("var3")); + } + + @Test + void should_returnProcessInstance_filteredByVariable_whenAllFiltersMatch() { + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .buildAndSave(); + + VariableFilter matchingFilter1 = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var1", + VariableType.STRING, + "value1", + FilterOperator.EQUALS + ); + + VariableFilter matchingFilter2 = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var2", + VariableType.STRING, + "value2", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(matchingFilter1, matchingFilter2); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance.getId())); + } + + @Test + void should_not_returnProcessInstance_filteredByVariable_whenOneFilterDoesNotMatch() { + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .buildAndSave(); + + VariableFilter matchingFilter = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var1", + VariableType.STRING, + "value1", + FilterOperator.EQUALS + ); + + VariableFilter nonMatchingFilter = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var2", + VariableType.STRING, + "value3", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(matchingFilter, nonMatchingFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body("page.totalElements", equalTo(0)); + } + + @Test + void should_returnProcessInstances_filteredByStringVariable_exactMatch() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1")) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "other-value")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.STRING, + "value1", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByStringVariable_Contains() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "abcdefg")) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "other-value")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.STRING, + "bcde", + FilterOperator.LIKE + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByIntegerVariable_equals() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 1)) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 2)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + String.valueOf(1), + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByIntegerVariable_greaterThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 10)) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 2)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + String.valueOf(2), + FilterOperator.GREATER_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByIntegerVariable_greaterThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 10)) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 2)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + String.valueOf(2), + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByIntegerVariable_lessThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 2)) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 10)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + String.valueOf(10), + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByIntegerVariable_lessThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 2)) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 10)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + String.valueOf(10), + FilterOperator.LESS_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByIntegerVariable_range() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 4)) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 8)) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 15)) + .buildAndSave(); + + VariableFilter filterGt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + "4", + FilterOperator.GREATER_THAN + ); + + VariableFilter filterLt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + "15", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(filterGt, filterLt); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + + VariableFilter filterGtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + "4", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + VariableFilter filterLtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.INTEGER, + "15", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance3.getId())); + } + + @Test + void should_returnProcessInstances_filteredByBigDecimalVariable_equals() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("1.1"))) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("1.2"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "1.1", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByBigDecimalVariable_greaterThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("10.1"))) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("2.1"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "2.1", + FilterOperator.GREATER_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByBigDecimalVariable_greaterThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("10.1"))) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("2.1"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "2.1", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByBigDecimalVariable_lessThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("2.1"))) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("10.1"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "10.1", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByBigDecimalVariable_lessThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("2.1"))) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("10.1"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "10.1", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredBigdecimalVariable_range() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("4.8"))) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("15.16"))) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("23.42"))) + .buildAndSave(); + + VariableFilter filterGt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "4.8", + FilterOperator.GREATER_THAN + ); + + VariableFilter filterLt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "23.42", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(filterGt, filterLt); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + + VariableFilter filterGtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "4.8", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + VariableFilter filterLtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BIGDECIMAL, + "23.42", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance3.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDateVariable_equals() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-01", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDateVariable_greaterThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-01", + FilterOperator.GREATER_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDateVariable_greaterThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-01", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDateVariable_lessThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-02", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDateVariable_lessThanEquals() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-02", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDateVariable_range() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-03")) + .buildAndSave(); + + VariableFilter filterGt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-01", + FilterOperator.GREATER_THAN + ); + + VariableFilter filterLt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-03", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(filterGt, filterLt); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + + VariableFilter filterGtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-01", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + VariableFilter filterLtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATE, + "2024-09-03", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance3.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDatetimeVariable_equals() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:11:00.000+00:00", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDatetimeVariable_greaterThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:11:00.000+00:00", + FilterOperator.GREATER_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDatetimeVariable_greaterThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:11:00.000+00:00", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDatetimeVariable_lessThan() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:12:00.000+00:00", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDatetimeVariable_lessThanEqual() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:12:00.000+00:00", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByDatetimeVariable_range() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:13:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter filterGt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:11:00.000+00:00", + FilterOperator.GREATER_THAN + ); + + VariableFilter filterLt = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:13:00.000+00:00", + FilterOperator.LESS_THAN + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(filterGt, filterLt); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + + VariableFilter filterGtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:11:00.000+00:00", + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + VariableFilter filterLtEq = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.DATETIME, + "2024-09-01T00:13:00.000+00:00", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + requestBuilder = new ProcessInstanceSearchRequestBuilder().withProcessVariableFilters(filterGtEq, filterLtEq); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance3.getId())); + } + + @Test + void should_returnProcessInstances_filteredByBooleanVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BOOLEAN, true)) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BOOLEAN, false)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + PROCESS_DEFINITION_KEY, + "var1", + VariableType.BOOLEAN, + "true", + FilterOperator.EQUALS + ); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withProcessVariableFilters(variableFilter); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_sortedBy_RootFields() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withName("Nice name") + .withInitiator(USER) + .withStartDate(new Date(3000)) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withName("Good name") + .withInitiator(USER) + .withStartDate(new Date(2000)) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withName("Amazing name") + .withInitiator(USER) + .withStartDate(new Date(4000)) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort(new CloudRuntimeEntitySort("name", Sort.Direction.ASC, false, null, null)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body( + processInstanceIdJsonPath, + contains(processInstance3.getId(), processInstance2.getId(), processInstance1.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort(new CloudRuntimeEntitySort("startDate", Sort.Direction.DESC, false, null, null)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body( + processInstanceIdJsonPath, + contains(processInstance3.getId(), processInstance1.getId(), processInstance2.getId()) + ); + } + + @Test + void should_returnProcessInstances_sortedBy_StringProcessVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "cool")) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "amazing")) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "beautiful")) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.ASC, + true, + PROCESS_DEFINITION_KEY, + VariableType.STRING + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance2.getId(), processInstance3.getId(), processInstance1.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.STRING + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance1.getId(), processInstance3.getId(), processInstance2.getId()) + ); + } + + @Test + void should_returnProcessInstances_sortedBy_IntegerProcessVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 2)) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 3)) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.INTEGER, 1)) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.ASC, + true, + PROCESS_DEFINITION_KEY, + VariableType.INTEGER + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance3.getId(), processInstance1.getId(), processInstance2.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.INTEGER + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance2.getId(), processInstance1.getId(), processInstance3.getId()) + ); + } + + @Test + void should_returnProcessInstances_sortedBy_BigdecimalProcessVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("2.1"))) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("10.1"))) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BIGDECIMAL, new BigDecimal("5.1"))) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.ASC, + true, + PROCESS_DEFINITION_KEY, + VariableType.BIGDECIMAL + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance1.getId(), processInstance3.getId(), processInstance2.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.BIGDECIMAL + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance2.getId(), processInstance3.getId(), processInstance1.getId()) + ); + } + + @Test + void should_returnProcessInstances_sortedBy_DateProcessVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-03")) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-01")) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.DATE, "2024-09-02")) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort("var1", Sort.Direction.ASC, true, PROCESS_DEFINITION_KEY, VariableType.DATE) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance2.getId(), processInstance3.getId(), processInstance1.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.DATE + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance1.getId(), processInstance3.getId(), processInstance2.getId()) + ); + } + + @Test + void should_returnProcessInstances_sortedBy_DatetimeProcessVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:11:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:10:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.DATETIME, "2024-09-01T00:12:00.000+00:00") + ) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.ASC, + true, + PROCESS_DEFINITION_KEY, + VariableType.DATETIME + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance2.getId(), processInstance1.getId(), processInstance3.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.DATETIME + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + contains(processInstance3.getId(), processInstance1.getId(), processInstance2.getId()) + ); + } + + @Test + void should_returnProcessInstances_sortedBy_BooleanProcessVariable() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BOOLEAN, true)) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BOOLEAN, false)) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.BOOLEAN, true)) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.ASC, + true, + PROCESS_DEFINITION_KEY, + VariableType.BOOLEAN + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + containsInRelativeOrder(processInstance2.getId(), processInstance1.getId()) + ) + .body( + processInstanceIdJsonPath, + containsInRelativeOrder(processInstance2.getId(), processInstance3.getId()) + ); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.BOOLEAN + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(3)) + .body( + processInstanceIdJsonPath, + containsInRelativeOrder(processInstance1.getId(), processInstance2.getId()) + ) + .body( + processInstanceIdJsonPath, + containsInRelativeOrder(processInstance3.getId(), processInstance2.getId()) + ); + } + + @Test + void should_returnProcessInstances_withSortedElementsFirst() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withAppName("Nice app") + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "cool")) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var1", VariableType.STRING, "amazing")) + .buildAndSave(); + + ProcessInstanceEntity processInstance3 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withAppName("Best app ever") + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var2", VariableType.INTEGER, 4)) + .buildAndSave(); + + ProcessInstanceEntity processInstance4 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .withProcessDefinitionKey(PROCESS_DEFINITION_KEY) + .withVariables(new QueryTestUtils.VariableInput("var2", VariableType.INTEGER, 3)) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var1", + Sort.Direction.ASC, + true, + PROCESS_DEFINITION_KEY, + VariableType.STRING + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(4)) + .body(processInstanceIdJsonPath + "[0]", is(processInstance2.getId())) + .body(processInstanceIdJsonPath + "[1]", is(processInstance1.getId())); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort( + new CloudRuntimeEntitySort( + "var2", + Sort.Direction.DESC, + true, + PROCESS_DEFINITION_KEY, + VariableType.INTEGER + ) + ); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(4)) + .body(processInstanceIdJsonPath + "[0]", is(processInstance3.getId())) + .body(processInstanceIdJsonPath + "[1]", is(processInstance4.getId())); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort(new CloudRuntimeEntitySort("appName", Sort.Direction.DESC, false, null, null)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(4)) + .body(processInstanceIdJsonPath + "[0]", is(processInstance1.getId())) + .body(processInstanceIdJsonPath + "[1]", is(processInstance3.getId())); + } + + @Test + void should_returnBadRequest_when_sortParameterIsInvalid() { + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withSort(new CloudRuntimeEntitySort("var1", Sort.Direction.ASC, true, null, VariableType.STRING)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(400); + + requestBuilder = + new ProcessInstanceSearchRequestBuilder() + .withSort(new CloudRuntimeEntitySort("var1", Sort.Direction.ASC, true, PROCESS_DEFINITION_KEY, null)); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(400); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationAdminControllerIT.java index 59c0a5906ef..f7627ddbea0 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationAdminControllerIT.java @@ -30,7 +30,9 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.ApplicationRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ApplicationEntity; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; @@ -65,6 +67,9 @@ public class ApplicationAdminControllerIT { @MockBean private ApplicationRepository applicationRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private SecurityManager securityManager; @@ -77,6 +82,9 @@ public class ApplicationAdminControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private ProcessInstanceAdminService processInstanceAdminService; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationControllerIT.java index 8eeda2478e1..3a7219f87e8 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ApplicationControllerIT.java @@ -30,7 +30,9 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.ApplicationRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ApplicationEntity; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; @@ -65,6 +67,9 @@ public class ApplicationControllerIT { @MockBean private ApplicationRepository applicationRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private SecurityManager securityManager; @@ -77,6 +82,9 @@ public class ApplicationControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private ProcessInstanceAdminService processInstanceAdminService; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionAdminControllerIT.java index 06cbdd08b28..0a207c033e1 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionAdminControllerIT.java @@ -30,7 +30,9 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.security.TaskLookupRestrictionService; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; @@ -65,6 +67,9 @@ public class ProcessDefinitionAdminControllerIT { @MockBean private ProcessDefinitionRepository processDefinitionRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private SecurityManager securityManager; @@ -80,6 +85,9 @@ public class ProcessDefinitionAdminControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private ProcessInstanceAdminService processInstanceAdminService; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionControllerIT.java index f0702b5d887..8a5e196bcfb 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessDefinitionControllerIT.java @@ -35,7 +35,9 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.QProcessDefinitionEntity; import org.activiti.cloud.services.security.ProcessDefinitionRestrictionService; import org.activiti.cloud.services.security.TaskLookupRestrictionService; @@ -81,6 +83,9 @@ public class ProcessDefinitionControllerIT { @MockBean private SecurityManager securityManager; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private SecurityPoliciesManager securityPoliciesManager; @@ -93,6 +98,9 @@ public class ProcessDefinitionControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private ProcessInstanceAdminService processInstanceAdminService; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java index f012b4b7b44..f3c3f73d3df 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityAdminControllerIT.java @@ -21,6 +21,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.querydsl.core.types.Predicate; import jakarta.persistence.EntityManagerFactory; import java.util.Collections; import java.util.Date; @@ -34,6 +35,7 @@ import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.security.TaskLookupRestrictionService; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -90,6 +92,9 @@ public class ProcessInstanceEntityAdminControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private EntityManagerFactory entityManagerFactory; @@ -101,7 +106,7 @@ void setUp() { @Test public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { //given - given(processInstanceRepository.findAll(any(), any(Pageable.class))) + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) .willReturn( new PageImpl<>(Collections.singletonList(buildDefaultProcessInstance()), PageRequest.of(1, 10), 11) ); @@ -116,7 +121,7 @@ public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApp @Test public void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { //given - given(processInstanceRepository.findAll(any(), any(Pageable.class))) + given(processInstanceRepository.findAll(any(Predicate.class), any(Pageable.class))) .willReturn( new PageImpl<>(Collections.singletonList(buildDefaultProcessInstance()), PageRequest.of(1, 10), 11) ); diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java index 96c663bab54..fe9d7097bab 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityControllerIT.java @@ -37,6 +37,7 @@ import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ProcessInstanceEntity; import org.activiti.cloud.services.security.ProcessInstanceRestrictionService; import org.activiti.cloud.services.security.TaskLookupRestrictionService; @@ -98,6 +99,9 @@ public class ProcessInstanceEntityControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private EntityManagerFactory entityManagerFactory; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntitySearchAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntitySearchAdminControllerIT.java new file mode 100644 index 00000000000..2ee1179ae04 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntitySearchAdminControllerIT.java @@ -0,0 +1,107 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +import org.activiti.QueryRestTestApplication; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.util.ProcessInstanceSearchRequestBuilder; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + classes = { QueryRestTestApplication.class, AlfrescoWebAutoConfiguration.class }, + properties = { + "spring.main.banner-mode=off", + "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", + "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@TestPropertySource("classpath:application-test.properties") +@Testcontainers +@WithMockUser(username = AbstractProcessInstanceEntitySearchControllerIT.USER, roles = "ACTIVITI_ADMIN") +class ProcessInstanceEntitySearchAdminControllerIT extends AbstractProcessInstanceEntitySearchControllerIT { + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Override + protected String getSearchEndpoint() { + return "/admin/v1/process-instances/search"; + } + + @Test + void should_return_AllProcessInstances() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator("another-user") + .buildAndSave(); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body("{}") + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } + + @Test + void should_returnProcessInstances_filteredByInitiator() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator("user1") + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator("user2") + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator("user3").buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withInitiators("user1", "user2"); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntitySearchControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntitySearchControllerIT.java new file mode 100644 index 00000000000..2632330bb2b --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntitySearchControllerIT.java @@ -0,0 +1,110 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +import org.activiti.QueryRestTestApplication; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.util.ProcessInstanceSearchRequestBuilder; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + classes = { QueryRestTestApplication.class, AlfrescoWebAutoConfiguration.class }, + properties = { + "spring.main.banner-mode=off", + "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", + "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@TestPropertySource("classpath:application-test.properties") +@Testcontainers +@WithMockUser(username = AbstractProcessInstanceEntitySearchControllerIT.USER, roles = "ACTIVITI_USER") +class ProcessInstanceEntitySearchControllerIT extends AbstractProcessInstanceEntitySearchControllerIT { + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Override + protected String getSearchEndpoint() { + return "/v1/process-instances/search"; + } + + @Test + void should_return_RestrictedProcessInstances() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator(USER) + .buildAndSave(); + queryTestUtils.buildProcessInstance().withInitiator("anotheruser").buildAndSave(); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body("{}") + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(1)) + .body("_embedded.processInstances[0].id", equalTo(processInstance1.getId())); + } + + @Test + void should_returnProcessInstances_filteredByInitiator() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withInitiator("user1") + .withTasks(queryTestUtils.buildTask().withTaskCandidateUsers(USER)) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withInitiator("user2") + .withTasks(queryTestUtils.buildTask().withTaskCandidateUsers(USER)) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withInitiator("user3") + .withTasks(queryTestUtils.buildTask().withTaskCandidateUsers(USER)) + .buildAndSave(); + + ProcessInstanceSearchRequestBuilder requestBuilder = new ProcessInstanceSearchRequestBuilder() + .withInitiators("user1", "user2"); + + given() + .contentType(MediaType.APPLICATION_JSON) + .body(requestBuilder.buildJson()) + .when() + .post(getSearchEndpoint()) + .then() + .statusCode(200) + .body(processInstanceJsonPath, hasSize(2)) + .body(processInstanceIdJsonPath, hasItem(processInstance1.getId())) + .body(processInstanceIdJsonPath, hasItem(processInstance2.getId())); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksAdminControllerIT.java index fcccf5de5c9..215828df702 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksAdminControllerIT.java @@ -23,6 +23,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.querydsl.core.types.Predicate; import jakarta.persistence.EntityManagerFactory; import java.util.Collections; import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; @@ -30,7 +31,9 @@ import org.activiti.cloud.alfresco.argument.resolver.AlfrescoPageRequest; import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; @@ -67,6 +70,12 @@ public class ProcessInstanceEntityTasksAdminControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private VariableRepository processVariableRepository; + @MockBean private SecurityManager securityManager; @@ -97,7 +106,7 @@ public void getTasksShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsAp //given TaskEntity taskEntity = buildDefaultTask(); - given(taskRepository.findAll(any(), any(Pageable.class))) + given(taskRepository.findAll(any(Predicate.class), any(Pageable.class))) .willReturn( new PageImpl<>( Collections.singletonList(taskEntity), diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksControllerIT.java index 8f065b6ad3e..fac0ae1d1df 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityTasksControllerIT.java @@ -33,7 +33,9 @@ import org.activiti.cloud.alfresco.argument.resolver.AlfrescoPageRequest; import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.security.TaskLookupRestrictionService; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -71,6 +73,12 @@ public class ProcessInstanceEntityTasksControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private VariableRepository variableRepository; + @MockBean private UserGroupManager userGroupManager; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityVariableEntityControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityVariableEntityControllerIT.java index 27454f39ffb..cd01040f6c5 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityVariableEntityControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessInstanceEntityVariableEntityControllerIT.java @@ -23,6 +23,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.querydsl.core.types.Predicate; import jakarta.persistence.EntityManagerFactory; import java.util.Collections; import java.util.Date; @@ -33,6 +34,7 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ProcessVariableEntity; @@ -70,6 +72,9 @@ public class ProcessInstanceEntityVariableEntityControllerIT { @MockBean private VariableRepository variableRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private SecurityManager securityManager; @@ -112,7 +117,7 @@ public void getVariablesShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaType ProcessVariableEntity variableEntity = buildVariable(); - given(variableRepository.findAll(any(), eq(pageRequest))) + given(variableRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(variableEntity), pageRequest, 12)); //when @@ -148,7 +153,7 @@ public void getVariablesShouldReturnAllResultsUsingHalWhenMediaTypeIsApplication ProcessVariableEntity variableEntity = buildVariable(); - given(variableRepository.findAll(any(), eq(pageRequest))) + given(variableRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(variableEntity), pageRequest, 11)); //when diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelAdminControllerIT.java index 8d0c991ae33..510892e8d4b 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelAdminControllerIT.java @@ -31,8 +31,10 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.EntityFinder; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.ProcessModelRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ProcessDefinitionEntity; import org.activiti.cloud.services.query.model.ProcessModelEntity; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -64,6 +66,9 @@ public class ProcessModelAdminControllerIT { @MockBean private ProcessModelRepository processModelRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private UserGroupManager userGroupManager; @@ -82,6 +87,9 @@ public class ProcessModelAdminControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private ProcessInstanceAdminService processInstanceAdminService; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelControllerIT.java index c0e7eb5df9e..c65eb5c789b 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessModelControllerIT.java @@ -33,8 +33,10 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.EntityFinder; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.ProcessModelRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.ProcessDefinitionEntity; import org.activiti.cloud.services.query.model.ProcessModelEntity; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -69,6 +71,9 @@ public class ProcessModelControllerIT { @MockBean private SecurityPoliciesManager securityPoliciesManager; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private UserGroupManager userGroupManager; @@ -84,6 +89,9 @@ public class ProcessModelControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private ProcessInstanceAdminService processInstanceAdminService; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessVariableServiceIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessVariableServiceIT.java new file mode 100644 index 00000000000..f454f5e4c9d --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/ProcessVariableServiceIT.java @@ -0,0 +1,145 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.activiti.cloud.services.query.util.QueryTestUtils; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + properties = { "spring.main.banner-mode=off", "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false" } +) +@Testcontainers +@TestPropertySource("classpath:application-test.properties") +class ProcessVariableServiceIT { + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Autowired + ProcessVariableService processVariableService; + + @Autowired + private QueryTestUtils queryTestUtils; + + @Test + void should_fetchProcessVariables_forProcessInstances() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("process1") + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("process2") + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .buildAndSave(); + + Set variableKeys = Set.of( + new ProcessVariableKey("process1", "var1"), + new ProcessVariableKey("process2", "var2") + ); + + processVariableService.fetchProcessVariablesForProcessInstances( + Set.of(processInstance1, processInstance2), + variableKeys + ); + + assertThat(processInstance1.getVariables()) + .hasSize(1) + .first() + .satisfies(processVariableEntity -> { + assertThat(processVariableEntity.getName()).isEqualTo("var1"); + assertThat((String) processVariableEntity.getValue()).isEqualTo("value1"); + }); + + assertThat(processInstance2.getVariables()) + .hasSize(1) + .first() + .satisfies(processVariableEntity -> { + assertThat(processVariableEntity.getName()).isEqualTo("var2"); + assertThat((String) processVariableEntity.getValue()).isEqualTo("value2"); + }); + } + + @Test + void should_fetchProcessVariables_forTasks() { + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("process1") + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("process2") + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + Set variableKeys = Set.of( + new ProcessVariableKey("process1", "var1"), + new ProcessVariableKey("process2", "var2") + ); + + TaskEntity task1 = processInstance1.getTasks().iterator().next(); + TaskEntity task2 = processInstance2.getTasks().iterator().next(); + + processVariableService.fetchProcessVariablesForTasks(Set.of(task1, task2), variableKeys); + + assertThat(task1.getProcessVariables()) + .hasSize(1) + .first() + .satisfies(processVariableEntity -> { + assertThat(processVariableEntity.getName()).isEqualTo("var1"); + assertThat((String) processVariableEntity.getValue()).isEqualTo("value1"); + }); + + assertThat(task2.getProcessVariables()) + .hasSize(1) + .first() + .satisfies(processVariableEntity -> { + assertThat(processVariableEntity.getName()).isEqualTo("var2"); + assertThat((String) processVariableEntity.getValue()).isEqualTo("value2"); + }); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/RestrictVariableEntityQueryIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/RestrictVariableEntityQueryIT.java index c8a3ee4fc9d..6b893ee7520 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/RestrictVariableEntityQueryIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/RestrictVariableEntityQueryIT.java @@ -40,7 +40,11 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; /** * This is present in case of a future scenario where we need to filter task or process instance variables more generally rather than per task or per proc. @@ -48,8 +52,13 @@ @SpringBootTest @TestPropertySource("classpath:application-test.properties") @EnableAutoConfiguration +@Testcontainers public class RestrictVariableEntityQueryIT { + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + @Autowired private TaskRepository taskRepository; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskAdminControllerIT.java new file mode 100644 index 00000000000..d8587265ca1 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskAdminControllerIT.java @@ -0,0 +1,259 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.postProcessors; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.webAppContextSetup; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import org.activiti.QueryRestTestApplication; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateUserRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.TaskVariableRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.model.TaskVariableEntity; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.web.context.WebApplicationContext; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + classes = { QueryRestTestApplication.class, AlfrescoWebAutoConfiguration.class }, + properties = { + "spring.main.banner-mode=off", + "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", + "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@TestPropertySource("classpath:application-test.properties") +@Testcontainers +//TODO Make the test work using AlfrescoJackson2HttpMessageConverter to simulate the actual response that we have in real environment +public class TaskAdminControllerIT { + + @Autowired + private WebApplicationContext context; + + @Autowired + TaskControllerHelper taskControllerHelper; + + @Autowired + TaskRepository taskRepository; + + @Autowired + TaskVariableRepository taskVariableRepository; + + @Autowired + private ProcessInstanceRepository processInstanceRepository; + + @Autowired + private VariableRepository variableRepository; + + @Autowired + private TaskCandidateGroupRepository taskCandidateGroupRepository; + + @Autowired + private TaskCandidateUserRepository taskCandidateUserRepository; + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @BeforeEach + public void setUp() { + webAppContextSetup(context); + postProcessors(csrf().asHeader()); + taskRepository.deleteAll(); + taskVariableRepository.deleteAll(); + processInstanceRepository.deleteAll(); + variableRepository.deleteAll(); + taskCandidateGroupRepository.deleteAll(); + taskCandidateUserRepository.deleteAll(); + } + + @Test + @WithMockUser(username = "testadmin") + void should_returnTasks_withOnlyRequestedProcessVariables_whenSearchingByTaskVariableNameAndValue() { + ProcessInstanceEntity processInstanceEntity = createProcessInstance(); + Set processVariables = createProcessVariables(processInstanceEntity); + + TaskVariableEntity taskVariable1 = createTaskVariable(); + TaskVariableEntity taskVariable2 = createTaskVariable(); + + Set taskVariables = new HashSet<>(); + taskVariables.add(taskVariable1); + taskVariables.add(taskVariable2); + + createTaskWithVariables(processInstanceEntity, taskVariables, processVariables); + + processInstanceRepository.save(processInstanceEntity); + + ProcessVariableEntity variableToFetch = processVariables.stream().findFirst().get(); + + given() + .webAppContextSetup(context) + .accept("application/hal+json;charset=UTF-8") + .when() + .get( + "/admin/v1/tasks?maxItems=500&skipCount=0&sort=createdDate,desc&variableKeys=" + + processInstanceEntity.getProcessDefinitionKey() + + "/" + + variableToFetch.getName() + + "&variables.name=" + + taskVariable1.getName() + + "&variables.value=" + + taskVariable1.getValue() + ) + .then() + .statusCode(200) + .body("_embedded.tasks", hasSize(1)); + } + + @Test + @WithMockUser(username = "testadmin") + void should_parseTaskSearchRequest() { + String taskSearchRequest = + """ + { + "completedFrom": "2021-01-01T00:00:00Z", + "completedTo": "2021-01-01T00:00:00Z", + "candidateUserId": ["candidateUserId"], + "candidateGroupId": ["candidateGroupId"], + "processVariableFilters": [ + { + "processDefinitionKey": "processDefinitionKey", + "name": "name", + "type": "string", + "value": "value", + "operator": "eq" + } + ], + "taskVariableFilters": [ + { + "name": "name", + "type": "string", + "value": "value", + "operator": "eq" + } + ], + "processVariableKeys": ["processDef/varName"], + "onlyStandalone": true, + "onlyRoot": true, + "assignee": ["assignee"], + "name": ["name"], + "description": ["description"], + "priority": [1], + "status": ["CREATED"], + "completedBy": ["completedBy"] + } + """; + + given() + .webAppContextSetup(context) + .contentType(MediaType.APPLICATION_JSON) + .body(taskSearchRequest) + .when() + .post("/admin/v1/tasks/search") + .then() + .statusCode(200); + } + + @NotNull + private Set createProcessVariables(ProcessInstanceEntity processInstanceEntity) { + Set variables = new HashSet<>(); + + for (int i = 0; i < 2; i++) { + ProcessVariableEntity processVariableEntity = new ProcessVariableEntity(); + processVariableEntity.setName("name" + i); + processVariableEntity.setValue(UUID.randomUUID().toString()); + processVariableEntity.setType("string"); + processVariableEntity.setProcessInstanceId(processInstanceEntity.getId()); + processVariableEntity.setProcessDefinitionKey(processInstanceEntity.getProcessDefinitionKey()); + processVariableEntity.setProcessInstance(processInstanceEntity); + variables.add(processVariableEntity); + } + variableRepository.saveAll(variables); + processInstanceEntity.setVariables(variables); + processInstanceRepository.save(processInstanceEntity); + return variables; + } + + @NotNull + private TaskVariableEntity createTaskVariable() { + TaskVariableEntity taskVariableEntity = new TaskVariableEntity(); + taskVariableEntity.setName("name" + UUID.randomUUID()); + taskVariableEntity.setType("string"); + taskVariableEntity.setValue(UUID.randomUUID().toString()); + taskVariableRepository.save(taskVariableEntity); + return taskVariableEntity; + } + + private void createTaskWithVariables( + ProcessInstanceEntity processInstanceEntity, + Set taskVariables, + Set processVariables + ) { + TaskEntity taskEntity = new TaskEntity(); + String taskId = UUID.randomUUID().toString(); + taskEntity.setId(taskId); + taskEntity.setCreatedDate(new Date()); + taskEntity.setProcessInstance(processInstanceEntity); + taskEntity.setProcessInstanceId(processInstanceEntity.getId()); + taskEntity.setVariables(taskVariables); + taskEntity.setProcessVariables(processVariables); + taskRepository.save(taskEntity); + taskVariables.forEach(taskVariableEntity -> { + taskVariableEntity.setTaskId(taskId); + taskVariableEntity.setTask(taskEntity); + taskVariableEntity.setProcessInstance(processInstanceEntity); + taskVariableRepository.save(taskVariableEntity); + }); + } + + @NotNull + private ProcessInstanceEntity createProcessInstance() { + ProcessInstanceEntity processInstanceEntity = new ProcessInstanceEntity(); + String process = UUID.randomUUID().toString(); + processInstanceEntity.setId(process); + processInstanceEntity.setName(process); + processInstanceEntity.setInitiator("initiator"); + processInstanceEntity.setProcessDefinitionName(process); + processInstanceEntity.setProcessDefinitionKey(process); + processInstanceEntity.setServiceName("test"); + processInstanceRepository.save(processInstanceEntity); + return processInstanceEntity; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerHelperIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerHelperIT.java index dd5b82a806e..cca08501510 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerHelperIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerHelperIT.java @@ -19,12 +19,13 @@ import com.querydsl.core.types.Predicate; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.IntStream; +import java.util.stream.Stream; import org.activiti.cloud.api.task.model.QueryCloudTask; import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; @@ -47,24 +48,29 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.PagedModel; import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; @SpringBootTest( - properties = { - "spring.main.banner-mode=off", - "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", - "logging.level.org.hibernate.collection.spi=warn", - } + properties = { "spring.main.banner-mode=off", "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false" } ) @TestPropertySource("classpath:application-test.properties") @EnableAutoConfiguration +@Testcontainers public class TaskControllerHelperIT { + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + @Autowired TaskControllerHelper taskControllerHelper; @@ -211,9 +217,83 @@ public void should_return_PaginatedTasks_WithProcessVariables() { } @Test - void should_returnTask_evenIfItHashNoMatchingProcessVariables() { - ProcessInstanceEntity processInstanceEntity = createProcessInstance(); - Set variables = createProcessVariables(processInstanceEntity); + void should_returnBothTasks_whenOneTaskHasNoMatchingProcessVariablesFetchKeys() { + ProcessInstanceEntity processInstanceEntity1 = createProcessInstance("processDefinitionKey1"); + Set variables1 = createProcessVariables(processInstanceEntity1, 5); + + ProcessInstanceEntity processInstanceEntity2 = createProcessInstance("processDefinitionKey2"); + Set variables2 = createProcessVariables(processInstanceEntity2, 7); + + TaskEntity process1Task = new TaskEntity(); + String taskId = "task_id_1"; + process1Task.setId(taskId); + process1Task.setCreatedDate(new Date()); + process1Task.setProcessVariables(variables1); + process1Task.setProcessInstanceId(processInstanceEntity1.getId()); + taskRepository.save(process1Task); + + TaskEntity process2Task = new TaskEntity(); + String taskId2 = "task_id_2"; + process2Task.setId(taskId2); + process2Task.setCreatedDate(new Date()); + process2Task.setProcessVariables(variables2); + process2Task.setProcessInstanceId(processInstanceEntity2.getId()); + taskRepository.save(process2Task); + + Predicate predicate = null; + VariableSearch variableSearch = new VariableSearch(null, null, null); + + List filters = List.of(new RootTasksFilter(false), new StandAloneTaskFilter(false)); + + int pageSize = 30; + Pageable pageable = PageRequest.of(0, pageSize, Sort.by("createdDate").ascending()); + + List processVariableFetchKeys = variables1 + .stream() + .limit(3) + .map(v -> processInstanceEntity1.getProcessDefinitionKey() + "/" + v.getName()) + .toList(); + + PagedModel> response = taskControllerHelper.findAllWithProcessVariables( + predicate, + variableSearch, + pageable, + filters, + processVariableFetchKeys + ); + + assertThat(response.getContent()).hasSize(2); + Optional task1 = response + .getContent() + .stream() + .map(EntityModel::getContent) + .filter(t -> t.getId().equals(taskId)) + .findFirst(); + assertThat(task1) + .isPresent() + .get() + .extracting(QueryCloudTask::getProcessVariables) + .satisfies(pv -> assertThat(pv).hasSameSizeAs(processVariableFetchKeys)); + Optional task2 = response + .getContent() + .stream() + .map(EntityModel::getContent) + .filter(t -> t.getId().equals(taskId2)) + .findFirst(); + assertThat(task2) + .isPresent() + .get() + .extracting(QueryCloudTask::getProcessVariables) + .satisfies(pv -> assertThat(pv).isNullOrEmpty()); + } + + @Test + void should_returnTask_whenItHashNoMatchingProcessVariablesFetchKeys() { + String processDefinitionKey = "processDefinitionKey"; + ProcessInstanceEntity processInstanceEntity1 = createProcessInstance(processDefinitionKey); + ProcessInstanceEntity processInstanceEntity2 = createProcessInstance(processDefinitionKey); + Set variables1 = createProcessVariables(processInstanceEntity1, 2); + createProcessVariables(processInstanceEntity2, 2); TaskEntity taskEntity = new TaskEntity(); String taskId = "task_id"; @@ -223,9 +303,9 @@ void should_returnTask_evenIfItHashNoMatchingProcessVariables() { taskEntity.setTaskCandidateGroups(Set.of(groupCand)); TaskCandidateUserEntity usrCand = new TaskCandidateUserEntity(taskId, "user"); taskEntity.setTaskCandidateUsers(Set.of(usrCand)); - taskEntity.setProcessVariables(Collections.emptySet()); - taskEntity.setProcessInstance(processInstanceEntity); - taskEntity.setProcessInstanceId(processInstanceEntity.getId()); + taskEntity.setProcessVariables(variables1); + taskEntity.setProcessInstance(processInstanceEntity1); + taskEntity.setProcessInstanceId(processInstanceEntity1.getId()); taskCandidateGroupRepository.save(groupCand); taskCandidateUserRepository.save(usrCand); taskRepository.save(taskEntity); @@ -238,9 +318,9 @@ void should_returnTask_evenIfItHashNoMatchingProcessVariables() { int pageSize = 30; Pageable pageable = PageRequest.of(0, pageSize, Sort.by("createdDate").descending()); - List processVariableKeys = variables - .stream() - .map(v -> processInstanceEntity.getProcessDefinitionKey() + "/" + v.getName()) + List processVariableKeys = Stream + .of("other-variable", "another-variable") + .map(v -> processInstanceEntity1.getProcessDefinitionKey() + "/" + v) .toList(); PagedModel> response = taskControllerHelper.findAllWithProcessVariables( @@ -252,7 +332,6 @@ void should_returnTask_evenIfItHashNoMatchingProcessVariables() { ); assertThat(response.getContent()).hasSize(1); - assertThat(response.getContent().stream().toList().getFirst().getContent().getProcessVariables()).isEmpty(); } @@ -462,10 +541,13 @@ private List createStandaloneTasks() { } @NotNull - private Set createProcessVariables(ProcessInstanceEntity processInstanceEntity) { + private Set createProcessVariables( + ProcessInstanceEntity processInstanceEntity, + int numberOfVariables + ) { Set variables = new HashSet<>(); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < numberOfVariables; i++) { ProcessVariableEntity processVariableEntity = new ProcessVariableEntity(); processVariableEntity.setName("name" + i); processVariableEntity.setValue("id"); @@ -481,15 +563,25 @@ private Set createProcessVariables(ProcessInstanceEntity } @NotNull - private ProcessInstanceEntity createProcessInstance() { + private Set createProcessVariables(ProcessInstanceEntity processInstanceEntity) { + return createProcessVariables(processInstanceEntity, 8); + } + + @NotNull + private ProcessInstanceEntity createProcessInstance(String processDefinitionKey) { ProcessInstanceEntity processInstanceEntity = new ProcessInstanceEntity(); - processInstanceEntity.setId("processInstanceId"); + processInstanceEntity.setId(processDefinitionKey + "/id"); processInstanceEntity.setName("name"); processInstanceEntity.setInitiator("initiator"); processInstanceEntity.setProcessDefinitionName("test"); - processInstanceEntity.setProcessDefinitionKey("processDefinitionKey"); + processInstanceEntity.setProcessDefinitionKey(processDefinitionKey); processInstanceEntity.setServiceName("test"); processInstanceRepository.save(processInstanceEntity); return processInstanceEntity; } + + @NotNull + private ProcessInstanceEntity createProcessInstance() { + return createProcessInstance("processDefinitionKey"); + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerIT.java new file mode 100644 index 00000000000..7f93633d3e2 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskControllerIT.java @@ -0,0 +1,209 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.postProcessors; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.webAppContextSetup; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; + +import java.util.List; +import java.util.UUID; +import org.activiti.QueryRestTestApplication; +import org.activiti.api.runtime.shared.security.SecurityManager; +import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateUserRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.TaskCandidateGroupEntity; +import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.hamcrest.Matchers; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.web.context.WebApplicationContext; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + classes = { QueryRestTestApplication.class, AlfrescoWebAutoConfiguration.class }, + properties = { + "spring.main.banner-mode=off", + "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", + "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@TestPropertySource("classpath:application-test.properties") +@Testcontainers +class TaskControllerIT { + + @Autowired + private WebApplicationContext context; + + @Autowired + TaskRepository taskRepository; + + @Autowired + private ProcessInstanceRepository processInstanceRepository; + + @Autowired + private TaskCandidateGroupRepository taskCandidateGroupRepository; + + @Autowired + private TaskCandidateUserRepository taskCandidateUserRepository; + + @SpyBean + private SecurityManager securityManager; + + private static final String CURRENT_USER = "testuser"; + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @BeforeEach + public void setUp() { + webAppContextSetup(context); + postProcessors(csrf().asHeader()); + taskRepository.deleteAll(); + processInstanceRepository.deleteAll(); + taskCandidateGroupRepository.deleteAll(); + taskCandidateUserRepository.deleteAll(); + } + + @Test + @WithMockUser(username = CURRENT_USER) + void should_returnTasks_withOnlyRequestedProcessVariables_whenSearchingByTaskVariableNameAndValue() { + ProcessInstanceEntity processInstance = createProcessInstance(); + String otherUser = "other-user"; + processInstance.setInitiator(otherUser); + processInstanceRepository.save(processInstance); + + //Task to be retrieved because user is assignee + TaskEntity task1 = new TaskEntity(); + task1.setId(UUID.randomUUID().toString()); + task1.setProcessInstanceId(processInstance.getId()); + task1.setAssignee(CURRENT_USER); + task1.setOwner(otherUser); + taskRepository.save(task1); + + //Task to be retrieved because user is candidate for the task and task is not assigned + TaskEntity task2 = new TaskEntity(); + task2.setId(UUID.randomUUID().toString()); + task2.setProcessInstanceId(processInstance.getId()); + taskRepository.save(task2); + TaskCandidateUserEntity taskCandidateTask2 = new TaskCandidateUserEntity(); + taskCandidateTask2.setUserId(CURRENT_USER); + taskCandidateTask2.setTaskId(task2.getId()); + taskCandidateUserRepository.save(taskCandidateTask2); + + //Task NOT to be retrieved because user is candidate for the task but task is assigned + TaskEntity task3 = new TaskEntity(); + task3.setId(UUID.randomUUID().toString()); + task3.setProcessInstanceId(processInstance.getId()); + task3.setAssignee(otherUser); + taskRepository.save(task3); + TaskCandidateUserEntity taskCandidateTask3 = new TaskCandidateUserEntity(); + taskCandidateTask3.setUserId(CURRENT_USER); + taskCandidateTask3.setTaskId(task2.getId()); + taskCandidateUserRepository.save(taskCandidateTask3); + + //Task to be retrieved because user belongs to candidate group and task is not assigned + TaskEntity task4 = new TaskEntity(); + task4.setId(UUID.randomUUID().toString()); + task4.setProcessInstanceId(processInstance.getId()); + taskRepository.save(task4); + TaskCandidateGroupEntity taskCandidateGroup = new TaskCandidateGroupEntity(); + taskCandidateGroup.setGroupId("testgroup"); + taskCandidateGroup.setTaskId(task3.getId()); + taskCandidateGroupRepository.save(taskCandidateGroup); + + //Task NOT to be retrieved because user belongs to candidate group but task is assigned + TaskEntity task5 = new TaskEntity(); + task5.setId(UUID.randomUUID().toString()); + task5.setProcessInstanceId(processInstance.getId()); + task5.setAssignee(otherUser); + taskRepository.save(task5); + TaskCandidateGroupEntity taskCandidateGroup2 = new TaskCandidateGroupEntity(); + taskCandidateGroup2.setGroupId("testgroup"); + taskCandidateGroup2.setTaskId(task5.getId()); + taskCandidateGroupRepository.save(taskCandidateGroup2); + + //Task to be retrieved because user is owner + TaskEntity task6 = new TaskEntity(); + task6.setId(UUID.randomUUID().toString()); + task6.setProcessInstanceId(processInstance.getId()); + task6.setAssignee(otherUser); + task6.setOwner(CURRENT_USER); + taskRepository.save(task6); + + //Task to be retrieved because there are no candidate users and groups and task is not assigned + TaskEntity task7 = new TaskEntity(); + task7.setId(UUID.randomUUID().toString()); + task7.setProcessInstanceId(processInstance.getId()); + task7.setOwner(otherUser); + taskRepository.save(task7); + + Mockito.when(securityManager.getAuthenticatedUserGroups()).thenReturn(List.of("testgroup")); + + given() + .webAppContextSetup(context) + .contentType(MediaType.APPLICATION_JSON) + .body("{}") + .when() + .post("/v1/tasks/search") + .then() + .statusCode(200) + .body("_embedded.tasks", hasSize(5)) + .body( + "_embedded.tasks", + Matchers.hasItems( + Matchers.hasEntry("id", task1.getId()), + Matchers.hasEntry("id", task2.getId()), + Matchers.hasEntry("id", task4.getId()), + Matchers.hasEntry("id", task6.getId()), + Matchers.hasEntry("id", task7.getId()) + ) + ); + } + + @NotNull + private ProcessInstanceEntity createProcessInstance() { + ProcessInstanceEntity processInstanceEntity = new ProcessInstanceEntity(); + String process = UUID.randomUUID().toString(); + processInstanceEntity.setId(process); + processInstanceEntity.setName(process); + processInstanceEntity.setInitiator("testuser"); + processInstanceEntity.setProcessDefinitionName(process); + processInstanceEntity.setProcessDefinitionKey(process); + processInstanceEntity.setServiceName("test"); + processInstanceRepository.save(processInstanceEntity); + return processInstanceEntity; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityAdminControllerIT.java index 3925724fe55..40358725818 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityAdminControllerIT.java @@ -36,7 +36,9 @@ import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.EntityFinder; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.security.TaskLookupRestrictionService; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -74,9 +76,15 @@ public class TaskEntityAdminControllerIT { @MockBean private ProcessInstanceAdminService processInstanceAdminService; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + @MockBean private TaskRepository taskRepository; + @MockBean + private VariableRepository processVariableRepository; + @MockBean private EntityFinder entityFinder; @@ -116,7 +124,7 @@ public void allTasksShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsAp //given AlfrescoPageRequest pageRequest = new AlfrescoPageRequest(11, 10, PageRequest.of(0, 20)); - given(taskRepository.findAll(any(), eq(pageRequest))) + given(taskRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 12)); //when @@ -144,7 +152,7 @@ public void allTasksShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJ //given PageRequest pageRequest = PageRequest.of(1, 10); - given(taskRepository.findAll(any(), eq(pageRequest))) + given(taskRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 11)); //when diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityControllerIT.java index 6152bb2a9e7..21b8ad317f5 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityControllerIT.java @@ -21,9 +21,12 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.querydsl.core.types.Predicate; @@ -39,7 +42,9 @@ import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.EntityFinder; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskCandidateGroupEntity; import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; import org.activiti.cloud.services.query.model.TaskEntity; @@ -55,6 +60,7 @@ import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; @@ -65,13 +71,21 @@ @WebMvcTest(TaskController.class) @Import( - { QueryRestWebMvcAutoConfiguration.class, CommonModelAutoConfiguration.class, AlfrescoWebAutoConfiguration.class } + { + QueryRestWebMvcAutoConfiguration.class, + CommonModelAutoConfiguration.class, + AlfrescoWebAutoConfiguration.class, + CommonExceptionHandlerQuery.class, + } ) @EnableSpringDataWebSupport @AutoConfigureMockMvc @WithMockUser -@TestPropertySource("classpath:application-test.properties") -public class TaskEntityControllerIT { +@TestPropertySource( + locations = { "classpath:application-test.properties" }, + properties = "activiti.cloud.rest.max-items.enabled=true" +) +class TaskEntityControllerIT { @Autowired private MockMvc mockMvc; @@ -79,6 +93,12 @@ public class TaskEntityControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private VariableRepository processVariableRepository; + @MockBean private EntityFinder entityFinder; @@ -114,11 +134,11 @@ void setUp() { } @Test - public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { + void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { //given AlfrescoPageRequest pageRequest = new AlfrescoPageRequest(11, 10, PageRequest.of(0, 20)); - given(taskRepository.findAll(any(), eq(pageRequest))) + given(taskRepository.findAll(nullable(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 12)); //when @@ -142,12 +162,12 @@ public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApp } @Test - public void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { + void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJson() throws Exception { //given PageRequest pageRequest = PageRequest.of(1, 10); - given(taskRepository.findAll(any(), eq(pageRequest))) - .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 11)); + when(taskRepository.findAll(nullable(Predicate.class), any(Pageable.class))) + .thenReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 11)); //when mockMvc @@ -157,7 +177,7 @@ public void findAllShouldReturnAllResultsUsingHalWhenMediaTypeIsApplicationHalJs } @Test - public void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { + void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() throws Exception { //given TaskEntity taskEntity = buildDefaultTask(); given(entityFinder.findById(eq(taskRepository), eq(taskEntity.getId()), anyString())).willReturn(taskEntity); @@ -174,7 +194,7 @@ public void findByIdShouldUseAlfrescoMetadataWhenMediaTypeIsApplicationJson() th } @Test - public void should_returnCandidates_when_invokeGetTaskById() throws Exception { + void should_returnCandidates_when_invokeGetTaskById() throws Exception { //given TaskEntity taskEntity = buildDefaultTask(); taskEntity.setTaskCandidateGroups(buildCandidateGroups(taskEntity)); @@ -227,7 +247,7 @@ private Set buildCandidateUsers(TaskEntity taskEntity) } @Test - public void should_returnTaskPermissions_when_invokeGetTaskById() throws Exception { + void should_returnTaskPermissions_when_invokeGetTaskById() throws Exception { //given TaskEntity taskEntity = buildDefaultTask(); taskEntity.setTaskCandidateUsers(buildCandidateUsers(taskEntity)); @@ -250,4 +270,62 @@ public void should_returnTaskPermissions_when_invokeGetTaskById() throws Excepti .ofLength(1) .thatContains(TaskPermissions.VIEW); } + + @Test + void should_returnBadRequest_when_invokeWithPagingParametersExceedingLimits() throws Exception { + //given + AlfrescoPageRequest pageRequest = new AlfrescoPageRequest(1000, 1000, PageRequest.of(0, 1000)); + + given(taskRepository.findAll(nullable(Predicate.class), eq(pageRequest))) + .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 2000)); + + //when + mockMvc + .perform(get("/v1/tasks?skipCount=1000&maxItems=1001").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.entry.message").value("Exceeded max limit of 1000 elements")); + } + + @Test + void should_returnBadRequest_when_invokeWithPageParameterExceedingLimits() throws Exception { + //given + AlfrescoPageRequest pageRequest = new AlfrescoPageRequest(1000, 1000, PageRequest.of(0, 1000)); + + given(taskRepository.findAll(nullable(Predicate.class), eq(pageRequest))) + .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 2000)); + + //when + mockMvc + .perform(get("/v1/tasks?page=0&size=1001").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.entry.message").value("Exceeded max limit of 1000 elements")); + } + + @Test + void should_returnOK_when_invokeWithPagingParametersWithinLimits() throws Exception { + //given + AlfrescoPageRequest pageRequest = new AlfrescoPageRequest(0, 1000, PageRequest.of(0, 20)); + + given(taskRepository.findAll(nullable(Predicate.class), eq(pageRequest))) + .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 1001)); + + //when + mockMvc + .perform(get("/v1/tasks?skipCount=0&maxItems=1000").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void should_returnOK_when_invokeWithPageParameterWithinLimits() throws Exception { + //given + PageRequest pageRequest = PageRequest.of(0, 1000); + + given(taskRepository.findAll(nullable(Predicate.class), eq(pageRequest))) + .willReturn(new PageImpl<>(Collections.singletonList(buildDefaultTask()), pageRequest, 1001)); + + //when + mockMvc + .perform(get("/v1/tasks?page=0&size=1000").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } } diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityDeleteControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityDeleteControllerIT.java index b3e018501c5..1fe39e59d8c 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityDeleteControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityDeleteControllerIT.java @@ -34,7 +34,9 @@ import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.EntityFinder; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskEntity; import org.activiti.cloud.services.security.TaskLookupRestrictionService; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -70,6 +72,12 @@ public class TaskEntityDeleteControllerIT { @MockBean private TaskRepository taskRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private VariableRepository processVariableRepository; + @MockBean private SecurityManager securityManager; diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityVariableEntityControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityVariableEntityControllerIT.java index 0077203702a..92cc9dc3072 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityVariableEntityControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskEntityVariableEntityControllerIT.java @@ -23,6 +23,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.querydsl.core.types.Predicate; import jakarta.persistence.EntityManagerFactory; import java.util.Collections; import java.util.Date; @@ -33,8 +34,10 @@ import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; import org.activiti.cloud.services.query.app.repository.ProcessDefinitionRepository; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; import org.activiti.cloud.services.query.app.repository.TaskVariableRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskVariableEntity; import org.activiti.cloud.services.security.TaskLookupRestrictionService; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; @@ -70,6 +73,12 @@ public class TaskEntityVariableEntityControllerIT { @MockBean private TaskVariableRepository variableRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private VariableRepository processVariableRepository; + @MockBean private SecurityManager securityManager; @@ -110,7 +119,7 @@ public void getVariablesShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaType //given AlfrescoPageRequest pageRequest = new AlfrescoPageRequest(11, 10, PageRequest.of(0, 20)); TaskVariableEntity variableEntity = buildVariable(); - given(variableRepository.findAll(any(), eq(pageRequest))) + given(variableRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(variableEntity), pageRequest, 12)); //when @@ -141,7 +150,7 @@ public void getVariablesShouldReturnAllResultsUsingHalWhenMediaTypeIsApplication //given PageRequest pageRequest = PageRequest.of(1, 10); TaskVariableEntity variableEntity = buildVariable(); - given(variableRepository.findAll(any(), eq(pageRequest))) + given(variableRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(variableEntity), pageRequest, 11)); //when diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskSearchIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskSearchIT.java new file mode 100644 index 00000000000..21f11322f38 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/TaskSearchIT.java @@ -0,0 +1,3459 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.Date; +import java.util.List; +import java.util.Set; +import org.activiti.api.task.model.Task; +import org.activiti.cloud.api.task.model.QueryCloudTask; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.activiti.cloud.services.query.rest.payload.TaskSearchRequest; +import org.activiti.cloud.services.query.util.QueryTestUtils; +import org.activiti.cloud.services.query.util.TaskSearchRequestBuilder; +import org.joda.time.LocalDate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.data.domain.PageRequest; +import org.springframework.hateoas.EntityModel; +import org.springframework.test.context.TestPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + properties = { + "spring.main.banner-mode=off", + "spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false", + "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@Testcontainers +@TestPropertySource("classpath:application-test.properties") +class TaskSearchIT { + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + @Autowired + TaskControllerHelper taskControllerHelper; + + @Autowired + private QueryTestUtils queryTestUtils; + + @AfterEach + public void cleanUp() { + queryTestUtils.cleanUp(); + } + + @Test + void should_returnTask_filteredByProcessVariable_whenAllFiltersMatch() { + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter matchingFilter1 = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var1", + VariableType.STRING, + "value1", + FilterOperator.EQUALS + ); + + VariableFilter matchingFilter2 = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var2", + VariableType.STRING, + "value2", + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(matchingFilter1, matchingFilter2)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(processInstance.getTasks().stream().findFirst().get()); + } + + @Test + void should_not_returnTask_filteredByProcessVariable_when_OneFilterDoesNotMatch() { + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withVariables( + new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"), + new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter matchingFilter = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var1", + VariableType.STRING, + "value1", + FilterOperator.EQUALS + ); + + VariableFilter notMatchingFilter = new VariableFilter( + processInstance.getProcessDefinitionKey(), + "var2", + VariableType.STRING, + "not-matching-value", + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(matchingFilter, notMatchingFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).isEmpty(); + } + + @Test + void should_returnTask_filteredByTaskVariable_whenAllFiltersMatch() { + QueryTestUtils.VariableInput var1 = new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"); + QueryTestUtils.VariableInput var2 = new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2"); + + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withTasks(queryTestUtils.buildTask().withVariables(var1, var2)) + .buildAndSave(); + + VariableFilter matchingFilter1 = new VariableFilter( + null, + var1.name(), + VariableType.STRING, + var1.getValue(), + FilterOperator.EQUALS + ); + + VariableFilter matchingFilter2 = new VariableFilter( + null, + var2.name(), + VariableType.STRING, + var2.getValue(), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(matchingFilter1, matchingFilter2)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(processInstance.getTasks().stream().findFirst().get()); + } + + @Test + void should_not_returnTask_filteredByTaskVariable_when_OneFilterDoesNotMatch() { + QueryTestUtils.VariableInput var1 = new QueryTestUtils.VariableInput("var1", VariableType.STRING, "value1"); + QueryTestUtils.VariableInput var2 = new QueryTestUtils.VariableInput("var2", VariableType.STRING, "value2"); + + queryTestUtils + .buildProcessInstance() + .withTasks(queryTestUtils.buildTask().withVariables(var1, var2)) + .buildAndSave(); + + VariableFilter matchingFilter1 = new VariableFilter( + null, + var1.name(), + VariableType.STRING, + var1.getValue(), + FilterOperator.EQUALS + ); + + VariableFilter notMatchingFilter = new VariableFilter( + null, + var2.name(), + VariableType.STRING, + "not-matching-value", + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(matchingFilter1, notMatchingFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).isEmpty(); + } + + @Test + void should_returnTasks_filteredByStringProcessVariable_exactMatch() { + QueryTestUtils.VariableInput varToSearch = new QueryTestUtils.VariableInput( + "string-var", + VariableType.STRING, + "string-value" + ); + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("process-definition-key") + .withVariables(varToSearch) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("other-process-definition-key") + .withVariables( + new QueryTestUtils.VariableInput(varToSearch.name(), VariableType.STRING, "different-string-value") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varToSearch.name(), + VariableType.STRING, + varToSearch.getValue(), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> { + assertThat(task.getProcessInstanceId()).isEqualTo(processInstance1.getId()); + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> pv.getName().equals(varToSearch.name()) && pv.getValue().equals(varToSearch.value()) + ); + }); + } + + @Test + void should_returnTasks_filteredByStringTaskProcessVariable_exactMatch() { + QueryTestUtils.VariableInput varToSearch = new QueryTestUtils.VariableInput( + "string-var", + VariableType.STRING, + "string-value" + ); + + TaskEntity task1 = queryTestUtils.buildTask().withVariables(varToSearch).buildAndSave(); + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varToSearch.name(), VariableType.STRING, "other-value")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varToSearch.name(), + VariableType.STRING, + varToSearch.getValue(), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task1); + } + + @Test + void should_returnTasks_filteredByStringProcessVariable_contains() { + String varName = "string-var"; + String valueToSearch = "jaeger"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.STRING, "Eren Jaeger")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.STRING, "Frank Jaeger")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.STRING, "Jaeger")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.STRING, + valueToSearch, + FilterOperator.LIKE + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> + pv.getName().equals(varName) && + ((String) pv.getValue()).toLowerCase().contains(valueToSearch.toLowerCase()) + ) + ); + } + + @Test + void should_returnTasks_filteredByTaskProcessVariable_contains() { + String varName = "task-var"; + String valueToSearch = "fox"; + ProcessInstanceEntity processInstance = queryTestUtils + .buildProcessInstance() + .withTasks( + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.STRING, "Gray Fox")), + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.STRING, "Fox Hound")) + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.STRING, + valueToSearch, + FilterOperator.LIKE + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(processInstance.getTasks()); + } + + @Test + void should_returnTasks_filteredByIntegerProcessVariable_equals() { + String varName = "int-var"; + int valueToSearch = 42; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("process-definition-key") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, valueToSearch)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, valueToSearch + 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("different-process-definition-key") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, valueToSearch)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(valueToSearch), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .hasSize(1) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> pv.getName().equals(varName) && pv.getValue().equals(valueToSearch)) + ); + } + + @Test + void should_returnTasks_filteredByIntegerTaskVariable_equals() { + String varName = "int-var"; + int valueToSearch = 42; + QueryCloudTask task = queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, valueToSearch)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, valueToSearch + 1)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(valueToSearch), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByIntegerProcessVariable_greaterThan() { + String varName = "int-var"; + int lowerBound = 42; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound + 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound + 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .hasSize(1) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> pv.getName().equals(varName) && (int) pv.getValue() > lowerBound) + ); + } + + @Test + void should_returnTasks_filteredByIntegerTaskVariable_greaterThan() { + String varName = "int-var"; + int lowerBound = 42; + QueryCloudTask task = queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound + 1)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound)); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByIntegerProcessVariable_greaterThanOrEqual() { + String varName = "int-var"; + int lowerBound = 42; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound + 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound + 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> pv.getName().equals(varName) && (int) pv.getValue() >= lowerBound) + ); + } + + @Test + void should_returnTasks_filteredByIntegerTaskVariable_greaterThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "int-var"; + int lowerBound = 42; + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound + 1)) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, lowerBound - 1)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByIntegerProcessVariable_lessThan() { + String varName = "int-var"; + int upperBound = 42; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound - 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound - 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(upperBound), + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> pv.getName().equals(varName) && (int) pv.getValue() < upperBound) + ); + } + + @Test + void should_returnTasks_filteredByIntegerTaskVariable_lessThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "int-var"; + int upperBound = 42; + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound - 1)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(upperBound), + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByIntegerProcessVariable_lessThanOrEqual() { + String varName = "int-var"; + int upperBound = 42; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound - 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound - 1)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(upperBound), + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> pv.getName().equals(varName) && (int) pv.getValue() <= upperBound) + ); + } + + @Test + void should_returnTasks_filteredByIntegerTaskVariable_lessThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "int-var"; + int upperBound = 42; + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound - 1)) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, upperBound + 1)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(upperBound), + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByIntegerProcessVariable_range() { + String varName = "int-var"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 42)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 84)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 10)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 100)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(20), + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLtEq = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.INTEGER, + String.valueOf(84), + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilterGt, variableFilterLtEq)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrder( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> + pv.getName().equals(varName) && (int) pv.getValue() > 20 && (int) pv.getValue() <= 84 + ) + ); + } + + @Test + void should_returnTasks_filteredByIntegerTaskVariable_range() { + String varName = "int-var"; + + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 42)) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 84)) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 10)) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.INTEGER, 100)) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(20), + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLtEq = new VariableFilter( + null, + varName, + VariableType.INTEGER, + String.valueOf(84), + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilterGt, variableFilterLtEq)) + .build(); + + List expectedTasks = List.of(task1); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByBigDecimalProcessVariable_equals() { + String varName = "bigdecimal-var"; + BigDecimal valueToSearch = new BigDecimal("42.42"); + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, valueToSearch)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, valueToSearch)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + String.valueOf(valueToSearch), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> + pv.getName().equals(varName) && new BigDecimal(pv.getValue().toString()).equals(valueToSearch) + ) + ); + } + + @Test + void should_returnTasks_filteredByBigDecimalTaskVariable_equals() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "bigdecimal-var"; + BigDecimal valueToSearch = new BigDecimal("42.42"); + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, valueToSearch)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + String.valueOf(valueToSearch), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByBigDecimalProcessVariable_greaterThan() { + String varName = "bigdecimal-var"; + BigDecimal lowerBound = new BigDecimal("42.42"); + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, lowerBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(new BigDecimal(pv.getValue().toString())).isGreaterThan(lowerBound); + }) + ); + } + + @Test + void should_returnTasks_filteredByBigDecimalTaskVariable_greaterThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "bigdecimal-var"; + BigDecimal lowerBound = new BigDecimal("42.42"); + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, lowerBound)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByBigDecimalProcessVariable_greaterThanOrEqual() { + String varName = "bigdecimal-var"; + BigDecimal lowerBound = new BigDecimal("42.42"); + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, lowerBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(new BigDecimal(pv.getValue().toString())).isGreaterThanOrEqualTo(lowerBound); + }) + ); + } + + @Test + void should_returnTasks_filteredByBigDecimalTaskVariable_greaterThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "bigdecimal-var"; + BigDecimal lowerBound = new BigDecimal("42.42"); + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, lowerBound)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + String.valueOf(lowerBound), + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByBigDecimalProcessVariable_lessThan() { + String varName = "bigdecimal-var"; + BigDecimal upperBound = new BigDecimal("42.42"); + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, upperBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + String.valueOf(upperBound), + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(new BigDecimal(pv.getValue().toString())).isLessThan(upperBound); + }) + ); + } + + @Test + void should_returnTasks_filteredByBigDecimalTaskVariable_lessThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "bigdecimal-var"; + BigDecimal upperBound = new BigDecimal("42.42"); + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, upperBound)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + String.valueOf(upperBound), + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByBigDecimalProcessVariable_lessThanOrEqual() { + String varName = "bigdecimal-var"; + BigDecimal upperBound = new BigDecimal("42.42"); + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, upperBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + String.valueOf(upperBound), + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(new BigDecimal(pv.getValue().toString())).isLessThanOrEqualTo(upperBound); + }) + ); + } + + @Test + void should_returnTasks_filteredByBigDecimalTaskVariable_lessThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "bigdecimal-var"; + BigDecimal upperBound = new BigDecimal("42.42"); + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.41"))) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, upperBound)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42.43"))) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + String.valueOf(upperBound), + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByBigDecimalProcessVariable_range() { + String varName = "bigdecimal-var"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("84"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("10"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("100"))) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + "20", + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLtEq = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BIGDECIMAL, + "84", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilterGt, variableFilterLtEq)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .hasSize(2) + .containsExactlyInAnyOrder( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> + pv.getName().equals(varName) && + new BigDecimal(pv.getValue().toString()).compareTo(new BigDecimal("20")) > 0 && + ( + new BigDecimal(pv.getValue().toString()).compareTo(new BigDecimal("84")) < 0 || + new BigDecimal(pv.getValue().toString()).compareTo(new BigDecimal("84")) == 0 + ) + ) + ); + } + + @Test + void should_returnTasks_filteredByBigDecimalTaskVariable_range() { + String varName = "bigdecimal-var"; + + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("42"))) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("84"))) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("10"))) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BIGDECIMAL, new BigDecimal("100"))) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + "20", + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLt = new VariableFilter( + null, + varName, + VariableType.BIGDECIMAL, + "84", + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilterGt, variableFilterLt)) + .build(); + + List expectedTasks = List.of(task1); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByDateProcessVariable_equals() { + String varName = "date-var"; + String valueToSearch = "2024-08-02"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + valueToSearch, + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(LocalDate.parse(pv.getValue())).isEqualTo(LocalDate.parse(valueToSearch)); + }) + ); + } + + @Test + void should_returnTasks_filteredByDateTaskVariable_equals() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "date-var"; + String valueToSearch = "2024-08-02"; + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATE, + valueToSearch, + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByDateProcessVariable_greaterThan() { + String varName = "date-var"; + String lowerBound = "2024-08-02"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + lowerBound, + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(LocalDate.parse(pv.getValue())).isGreaterThan(LocalDate.parse(lowerBound)); + }) + ); + } + + @Test + void should_returnTasks_filteredByDateTaskVariable_greaterThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "date-var"; + String lowerBound = "2024-08-02"; + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATE, + lowerBound, + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByDateProcessVariable_greaterThanOrEqual() { + String varName = "date-var"; + String lowerBound = "2024-08-02"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + lowerBound, + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(LocalDate.parse(pv.getValue())).isGreaterThanOrEqualTo(LocalDate.parse(lowerBound)); + }) + ); + } + + @Test + void should_returnTasks_filteredByDateTaskVariable_greaterThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "date-var"; + String lowerBound = "2024-08-02"; + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATE, + lowerBound, + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByDateProcessVariable_lessThan() { + String varName = "date-var"; + String upperBound = "2024-08-02"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + upperBound, + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(LocalDate.parse(pv.getValue())).isLessThan(LocalDate.parse(upperBound)); + }) + ); + } + + @Test + void should_returnTasks_filteredByDateTaskVariable_lessThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "date-var"; + String upperBound = "2024-08-02"; + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATE, + upperBound, + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasks_filteredByDateProcessVariable_lessThanOrEqual() { + String varName = "date-var"; + String upperBound = "2024-08-02"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + upperBound, + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(LocalDate.parse(pv.getValue())).isLessThanOrEqualTo(LocalDate.parse(upperBound)); + }) + ); + } + + @Test + void should_returnTasks_filteredByDateTaskVariable_lessThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "date-var"; + String upperBound = "2024-08-02"; + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-03")) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATE, + upperBound, + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByDateProcessVariable_range() { + String varName = "date-var"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-04")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-05")) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + "2024-08-01", + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLt = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATE, + "2024-08-04", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilterGt, variableFilterLt)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrder( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> + pv.getName().equals(varName) && + LocalDate.parse(pv.getValue()).isAfter(LocalDate.parse("2024-08-01")) && + ( + LocalDate.parse(pv.getValue()).isBefore(LocalDate.parse("2024-08-04")) || + LocalDate.parse(pv.getValue()).isEqual(LocalDate.parse("2024-08-04")) + ) + ) + ); + } + + @Test + void should_returnTasks_filteredByDateTaskVariable_range() { + String varName = "date-var"; + + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-02")) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-04")) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-01")) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATE, "2024-08-05")) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + null, + varName, + VariableType.DATE, + "2024-08-01", + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLt = new VariableFilter( + null, + varName, + VariableType.DATE, + "2024-08-04", + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilterGt, variableFilterLt)) + .build(); + + List expectedTasks = List.of(task1); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByDateTimeProcessVariable_equals() { + String varName = "datetime-var"; + String valueToSearch = "2024-08-02T00:11:00.000+00:00"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:11:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:11:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + valueToSearch, + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(OffsetDateTime.parse(pv.getValue())).isEqualTo(OffsetDateTime.parse(valueToSearch)); + }) + ); + } + + @Test + void should_returnTasks_filteredByDateTimeTaskVariable_equals() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "datetime-var"; + + String valueToSearch = "2024-08-02T00:11:00.000+00:00"; + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, valueToSearch)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATETIME, + valueToSearch, + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasksFilteredByDateTimeProcessVariable_greaterThan() { + String varName = "datetime-var"; + String lowerBound = "2024-08-02T00:11:00.000+00:00"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, lowerBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + lowerBound, + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(OffsetDateTime.parse(pv.getValue())).isAfter(OffsetDateTime.parse(lowerBound)); + }) + ); + } + + @Test + void should_returnTasksFilteredByDateTimeTaskVariable_greaterThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "datetime-var"; + String lowerBound = "2024-08-02T00:11:00.000+00:00"; + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, lowerBound)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATETIME, + lowerBound, + FilterOperator.GREATER_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasksFilteredByDateTimeProcessVariable_greaterThanOrEqual() { + String varName = "datetime-var"; + String lowerBound = "2024-08-02T00:11:00.000+00:00"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, lowerBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + lowerBound, + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(OffsetDateTime.parse(pv.getValue())) + .isAfterOrEqualTo(OffsetDateTime.parse(lowerBound)); + }) + ); + } + + @Test + void should_returnTasksFilteredByDateTimeTaskVariable_greaterThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "datetime-var"; + String lowerBound = "2024-08-02T00:11:00.000+00:00"; + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, lowerBound)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATETIME, + lowerBound, + FilterOperator.GREATER_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasksFilteredByDateTimeProcessVariable_lessThan() { + String varName = "datetime-var"; + String upperBound = "2024-08-02T00:11:00.000+00:00"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, upperBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + upperBound, + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(OffsetDateTime.parse(pv.getValue())).isBefore(OffsetDateTime.parse(upperBound)); + }) + ); + } + + @Test + void should_returnTasksFilteredByDateTimeTaskVariable_lessThan() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "datetime-var"; + String upperBound = "2024-08-02T00:11:00.000+00:00"; + + QueryCloudTask task = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, upperBound)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATETIME, + upperBound, + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task); + } + + @Test + void should_returnTasksFilteredByDateTimeProcessVariable_lessThanOrEqual() { + String varName = "datetime-var"; + String upperBound = "2024-08-02T00:11:00.000+00:00"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, upperBound)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + upperBound, + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrderElementsOf(expectedTasks) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat(OffsetDateTime.parse(pv.getValue())) + .isBeforeOrEqualTo(OffsetDateTime.parse(upperBound)); + }) + ); + } + + @Test + void should_returnTasksFilteredByDateTimeTaskVariable_lessThanOrEqual() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "datetime-var"; + String upperBound = "2024-08-02T00:11:00.000+00:00"; + + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, upperBound)) + .buildAndSave(); + queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.DATETIME, + upperBound, + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List expectedTasks = List.of(task1, task2); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasks_filteredByDateTimeProcessVariable_range() { + String varName = "datetime-var"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:11:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:12:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:14:00.000+00:00") + ) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + "2024-08-02T00:10:00.000+00:00", + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLt = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.DATETIME, + "2024-08-02T00:13:00.000+00:00", + FilterOperator.LESS_THAN_OR_EQUAL + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilterGt, variableFilterLt)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactlyInAnyOrder( + processInstance1.getTasks().iterator().next(), + processInstance2.getTasks().iterator().next() + ) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .anyMatch(pv -> + pv.getName().equals(varName) && + OffsetDateTime + .parse(pv.getValue()) + .isAfter(OffsetDateTime.parse("2024-08-02T00:10:00.000+00:00")) && + OffsetDateTime + .parse(pv.getValue()) + .isBefore(OffsetDateTime.parse("2024-08-02T00:13:00.000+00:00")) + ) + ); + } + + @Test + void should_returnTasks_filteredByDateTimeTaskVariable_range() { + String varName = "datetime-var"; + + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:11:00.000+00:00") + ) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:10:00.000+00:00") + ) + .buildAndSave(); + + queryTestUtils + .buildTask() + .withVariables( + new QueryTestUtils.VariableInput(varName, VariableType.DATETIME, "2024-08-02T00:14:00.000+00:00") + ) + .buildAndSave(); + + VariableFilter variableFilterGt = new VariableFilter( + null, + varName, + VariableType.DATETIME, + "2024-08-02T00:10:00.000+00:00", + FilterOperator.GREATER_THAN + ); + + VariableFilter variableFilterLt = new VariableFilter( + null, + varName, + VariableType.DATETIME, + "2024-08-02T00:13:00.000+00:00", + FilterOperator.LESS_THAN + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilterGt, variableFilterLt)) + .build(); + + List expectedTasks = List.of(task1); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrderElementsOf(expectedTasks); + } + + @Test + void should_returnTasksFilteredByBooleanProcessVariable() { + String varName = "boolean-var"; + + ProcessInstanceEntity processInstance1 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("processDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BOOLEAN, true)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + ProcessInstanceEntity processInstance2 = queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey(processInstance1.getProcessDefinitionKey()) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BOOLEAN, false)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + queryTestUtils + .buildProcessInstance() + .withProcessDefinitionKey("differentProcessDefinitionKey") + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BOOLEAN, true)) + .withTasks(queryTestUtils.buildTask()) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BOOLEAN, + String.valueOf(true), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance1.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat((boolean) pv.getValue()).isTrue(); + }) + ); + + variableFilter = + new VariableFilter( + processInstance1.getProcessDefinitionKey(), + varName, + VariableType.BOOLEAN, + String.valueOf(false), + FilterOperator.EQUALS + ); + + taskSearchRequest = new TaskSearchRequestBuilder().withProcessVariableFilters(Set.of(variableFilter)).build(); + + retrievedTasks = + taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks) + .containsExactly(processInstance2.getTasks().iterator().next()) + .allSatisfy(task -> + assertThat(task.getProcessVariables()) + .isNotEmpty() + .allSatisfy(pv -> { + assertThat(pv.getName()).isEqualTo(varName); + assertThat((boolean) pv.getValue()).isFalse(); + }) + ); + } + + @Test + void should_returnTasksFilteredByBooleanTaskVariable() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + String varName = "boolean-var"; + + QueryCloudTask task1 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BOOLEAN, true)) + .buildAndSave(); + QueryCloudTask task2 = queryTestUtils + .buildTask() + .withParentProcess(processInstance) + .withVariables(new QueryTestUtils.VariableInput(varName, VariableType.BOOLEAN, false)) + .buildAndSave(); + + VariableFilter variableFilter = new VariableFilter( + null, + varName, + VariableType.BOOLEAN, + String.valueOf(true), + FilterOperator.EQUALS + ); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withTaskVariableFilters(Set.of(variableFilter)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task1); + + variableFilter = + new VariableFilter(null, varName, VariableType.BOOLEAN, String.valueOf(false), FilterOperator.EQUALS); + + taskSearchRequest = new TaskSearchRequestBuilder().withTaskVariableFilters(Set.of(variableFilter)).build(); + + retrievedTasks = + taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(task2); + } + + @Test + void should_returnStandaloneTasksOnly() { + TaskEntity standalone = queryTestUtils.buildTask().buildAndSave(); + + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + queryTestUtils.buildTask().withParentProcess(processInstance).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().onlyStandalone().build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(standalone); + } + + @Test + void should_returnRootTasksOnly() { + ProcessInstanceEntity processInstance = queryTestUtils.buildProcessInstance().buildAndSave(); + TaskEntity rootTask = queryTestUtils.buildTask().withParentProcess(processInstance).buildAndSave(); + queryTestUtils.buildTask().withParentTask(rootTask).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().onlyRoot().build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactly(rootTask); + } + + @Test + void should_returnTasksFilteredByNameContains() { + TaskEntity task1 = queryTestUtils.buildTask().withName("Darth Vader").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withName("Frodo Baggins").buildAndSave(); + queryTestUtils.buildTask().withName("Duke Leto").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withName("darth", "baggins").build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByDescriptionContains() { + TaskEntity task1 = queryTestUtils.buildTask().withDescription("Darth Vader").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withDescription("Frodo Baggins").buildAndSave(); + queryTestUtils.buildTask().withDescription("Duke Leto").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withDescription("darth", "baggins") + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByProcessDefinitionName() { + TaskEntity task1 = queryTestUtils.buildTask().withProcessDefinitionName("name1").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withProcessDefinitionName("name2").buildAndSave(); + queryTestUtils.buildTask().withProcessDefinitionName("name3").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withProcessDefinitionName("name1", "name2") + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByPriority() { + TaskEntity task1 = queryTestUtils.buildTask().withPriority(1).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withPriority(2).buildAndSave(); + queryTestUtils.buildTask().withPriority(3).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withPriority(1, 2).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByStatus() { + TaskEntity task1 = queryTestUtils.buildTask().withStatus(Task.TaskStatus.CREATED).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withStatus(Task.TaskStatus.ASSIGNED).buildAndSave(); + queryTestUtils.buildTask().withStatus(Task.TaskStatus.COMPLETED).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withStatus(Task.TaskStatus.CREATED, Task.TaskStatus.ASSIGNED) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCompletedBy() { + TaskEntity task1 = queryTestUtils.buildTask().withCompletedBy("Jimmy Page").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withCompletedBy("Robert Plant").buildAndSave(); + queryTestUtils.buildTask().withCompletedBy("John Bonham").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withCompletedBy("Jimmy Page", "Robert Plant") + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByAssignee() { + TaskEntity task1 = queryTestUtils.buildTask().withAssignee("Kimi Raikkonen").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withAssignee("Lewis Hamilton").buildAndSave(); + queryTestUtils.buildTask().withAssignee("Sebastian Vettel").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withAssignees("Kimi Raikkonen", "Lewis Hamilton") + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCreatedFrom() { + TaskEntity task1 = queryTestUtils.buildTask().withCreatedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withCreatedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withCreatedDate(new Date(500)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withCreatedFrom(new Date(900)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCreatedTo() { + TaskEntity task1 = queryTestUtils.buildTask().withCreatedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withCreatedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withCreatedDate(new Date(3000)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withCreatedTo(new Date(2500)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByLastModifiedFrom() { + TaskEntity task1 = queryTestUtils.buildTask().withLastModifiedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withLastModifiedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withLastModifiedDate(new Date(500)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withLastModifiedFrom(new Date(900)) + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByLastModifiedTo() { + TaskEntity task1 = queryTestUtils.buildTask().withLastModifiedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withLastModifiedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withLastModifiedDate(new Date(3000)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withLastModifiedTo(new Date(2500)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByLastClaimedFrom() { + TaskEntity task1 = queryTestUtils.buildTask().withClaimedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withClaimedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withClaimedDate(new Date(500)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withLastClaimedFrom(new Date(900)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByLastClaimedTo() { + TaskEntity task1 = queryTestUtils.buildTask().withClaimedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withClaimedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withClaimedDate(new Date(3000)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withLastClaimedTo(new Date(2500)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByDueDateFrom() { + TaskEntity task1 = queryTestUtils.buildTask().withDueDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withDueDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withDueDate(new Date(500)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withDueDateFrom(new Date(900)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByDueDateTo() { + TaskEntity task1 = queryTestUtils.buildTask().withDueDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withDueDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withDueDate(new Date(3000)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withDueDateTo(new Date(2500)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCompletedFrom() { + TaskEntity task1 = queryTestUtils.buildTask().withCompletedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withCompletedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withCompletedDate(new Date(500)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withCompletedFrom(new Date(900)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCompletedTo() { + TaskEntity task1 = queryTestUtils.buildTask().withCompletedDate(new Date(1000)).buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withCompletedDate(new Date(2000)).buildAndSave(); + queryTestUtils.buildTask().withCompletedDate(new Date(3000)).buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder().withCompletedTo(new Date(2500)).build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCandidateUserId() { + TaskEntity task1 = queryTestUtils.buildTask().withTaskCandidateUsers("user1").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withTaskCandidateUsers("user2").buildAndSave(); + queryTestUtils.buildTask().withTaskCandidateUsers("user3").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withCandidateUserId("user1", "user2") + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } + + @Test + void should_returnTasksFilteredByCandidateGroupId() { + TaskEntity task1 = queryTestUtils.buildTask().withTaskCandidateGroups("group1").buildAndSave(); + TaskEntity task2 = queryTestUtils.buildTask().withTaskCandidateGroups("group2").buildAndSave(); + queryTestUtils.buildTask().withTaskCandidateGroups("group3").buildAndSave(); + + TaskSearchRequest taskSearchRequest = new TaskSearchRequestBuilder() + .withCandidateGroupId("group1", "group2") + .build(); + + List retrievedTasks = taskControllerHelper + .searchTasksUnrestricted(taskSearchRequest, PageRequest.of(0, 100)) + .getContent() + .stream() + .map(EntityModel::getContent) + .toList(); + + assertThat(retrievedTasks).containsExactlyInAnyOrder(task1, task2); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/VariableEntityAdminControllerIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/VariableEntityAdminControllerIT.java index cdc138534e4..5d83af44bc0 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/VariableEntityAdminControllerIT.java +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/VariableEntityAdminControllerIT.java @@ -23,6 +23,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.querydsl.core.types.Predicate; import jakarta.persistence.EntityManagerFactory; import java.util.Collections; import java.util.Date; @@ -33,8 +34,10 @@ import org.activiti.cloud.alfresco.argument.resolver.AlfrescoPageRequest; import org.activiti.cloud.alfresco.config.AlfrescoWebAutoConfiguration; import org.activiti.cloud.conf.QueryRestWebMvcAutoConfiguration; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; import org.activiti.cloud.services.query.app.repository.TaskRepository; import org.activiti.cloud.services.query.app.repository.TaskVariableRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.TaskVariableEntity; import org.activiti.core.common.spring.security.policies.SecurityPoliciesManager; import org.activiti.core.common.spring.security.policies.conf.SecurityPoliciesProperties; @@ -68,6 +71,12 @@ public class VariableEntityAdminControllerIT { @MockBean private TaskVariableRepository variableRepository; + @MockBean + private ProcessInstanceRepository processInstanceRepository; + + @MockBean + private VariableRepository processVariableRepository; + @MockBean private UserGroupManager userGroupManager; @@ -121,7 +130,7 @@ public void findAllShouldReturnAllResultsUsingAlfrescoMetadataWhenMediaTypeIsApp ); variableEntity.setValue("John"); - given(variableRepository.findAll(any(), eq(pageRequest))) + given(variableRepository.findAll(any(Predicate.class), eq(pageRequest))) .willReturn(new PageImpl<>(Collections.singletonList(variableEntity), pageRequest, 12)); //when diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/specification/SpecificationSupportIT.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/specification/SpecificationSupportIT.java new file mode 100644 index 00000000000..cda53414a96 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/rest/specification/SpecificationSupportIT.java @@ -0,0 +1,233 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.rest.specification; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import java.util.List; +import java.util.stream.Stream; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity_; +import org.activiti.cloud.services.query.rest.filter.FilterOperator; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.jpa.domain.Specification; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest( + properties = { + "spring.main.banner-mode=off", "spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect", + } +) +@Testcontainers +class SpecificationSupportIT { + + @Autowired + VariableRepository variableRepository; + + @Container + @ServiceConnection + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:15-alpine"); + + private static Stream provideArguments() { + return Stream.of( + Arguments.of(VariableType.STRING, FilterOperator.EQUALS, "value1", List.of("value1", "value2"), 1), + Arguments.of(VariableType.STRING, FilterOperator.LIKE, "value", List.of("value1", "Value2", "other"), 2), + Arguments.of(VariableType.BOOLEAN, FilterOperator.EQUALS, "true", List.of(true, false), 1), + Arguments.of(VariableType.BIGDECIMAL, FilterOperator.EQUALS, "1.2", List.of(1.2, 2), 1), + Arguments.of(VariableType.BIGDECIMAL, FilterOperator.GREATER_THAN, "1.2", List.of(1.3, 1), 1), + Arguments.of(VariableType.BIGDECIMAL, FilterOperator.LESS_THAN, "1.2", List.of(1.1, 2), 1), + Arguments.of(VariableType.BIGDECIMAL, FilterOperator.GREATER_THAN_OR_EQUAL, "1.2", List.of(1.2, 1.3, 1), 2), + Arguments.of(VariableType.BIGDECIMAL, FilterOperator.LESS_THAN_OR_EQUAL, "1.2", List.of(1.2, 1.1, 2), 2), + Arguments.of(VariableType.INTEGER, FilterOperator.EQUALS, "1", List.of(1, 2), 1), + Arguments.of(VariableType.INTEGER, FilterOperator.GREATER_THAN, "1", List.of(2, 1), 1), + Arguments.of(VariableType.INTEGER, FilterOperator.LESS_THAN, "1", List.of(0, 1), 1), + Arguments.of(VariableType.INTEGER, FilterOperator.GREATER_THAN_OR_EQUAL, "1", List.of(1, 2, 0), 2), + Arguments.of(VariableType.INTEGER, FilterOperator.LESS_THAN_OR_EQUAL, "1", List.of(1, 0, 2), 2), + Arguments.of( + VariableType.DATE, + FilterOperator.EQUALS, + "2021-01-01", + List.of("2021-01-01", "2021-01-02"), + 1 + ), + Arguments.of( + VariableType.DATE, + FilterOperator.GREATER_THAN, + "2021-01-01", + List.of("2021-01-02", "2021-01-01"), + 1 + ), + Arguments.of( + VariableType.DATE, + FilterOperator.LESS_THAN, + "2021-01-02", + List.of("2021-01-01", "2021-01-02"), + 1 + ), + Arguments.of( + VariableType.DATE, + FilterOperator.GREATER_THAN_OR_EQUAL, + "2021-01-02", + List.of("2021-01-03", "2021-01-02", "2021-01-01"), + 2 + ), + Arguments.of( + VariableType.DATE, + FilterOperator.LESS_THAN_OR_EQUAL, + "2021-01-02", + List.of("2021-01-01", "2021-01-02", "2021-01-03"), + 2 + ), + Arguments.of( + VariableType.DATETIME, + FilterOperator.EQUALS, + "2024-08-02T00:11:00.000+00:00", + List.of("2024-08-02T00:11:00.000+00:00", "2024-08-02T00:11:22.000+00:00"), + 1 + ), + Arguments.of( + VariableType.DATETIME, + FilterOperator.GREATER_THAN, + "2024-08-02T00:11:00.000+00:00", + List.of("2024-08-02T00:11:22.000+00:00", "2024-08-02T00:11:00.000+00:00"), + 1 + ), + Arguments.of( + VariableType.DATETIME, + FilterOperator.LESS_THAN, + "2024-08-02T00:11:22.000+00:00", + List.of("2024-08-02T00:11:00.000+00:00", "2024-08-02T00:11:22.000+00:00"), + 1 + ), + Arguments.of( + VariableType.DATETIME, + FilterOperator.GREATER_THAN_OR_EQUAL, + "2024-08-02T00:11:22.000+00:00", + List.of( + "2024-08-02T00:11:22.000+00:00", + "2024-08-02T00:11:44.000+00:00", + "2024-08-02T00:11:00.000+00:00" + ), + 2 + ), + Arguments.of( + VariableType.DATETIME, + FilterOperator.LESS_THAN_OR_EQUAL, + "2024-08-02T00:11:22.000+00:00", + List.of( + "2024-08-02T00:11:00.000+00:00", + "2024-08-02T00:11:22.000+00:00", + "2024-08-02T00:11:44.000+00:00" + ), + 2 + ) + ); + } + + private static Stream provideArgumentsThatShouldThrow() { + return Stream.of( + Arguments.of(VariableType.STRING, FilterOperator.GREATER_THAN), + Arguments.of(VariableType.STRING, FilterOperator.LESS_THAN), + Arguments.of(VariableType.STRING, FilterOperator.GREATER_THAN_OR_EQUAL), + Arguments.of(VariableType.STRING, FilterOperator.LESS_THAN_OR_EQUAL), + Arguments.of(VariableType.BOOLEAN, FilterOperator.LIKE), + Arguments.of(VariableType.BOOLEAN, FilterOperator.GREATER_THAN), + Arguments.of(VariableType.BOOLEAN, FilterOperator.LESS_THAN), + Arguments.of(VariableType.BOOLEAN, FilterOperator.GREATER_THAN_OR_EQUAL), + Arguments.of(VariableType.BOOLEAN, FilterOperator.LESS_THAN_OR_EQUAL), + Arguments.of(VariableType.BIGDECIMAL, FilterOperator.LIKE), + Arguments.of(VariableType.INTEGER, FilterOperator.LIKE) + ); + } + + @AfterEach + void tearDown() { + variableRepository.deleteAll(); + } + + @ParameterizedTest + @MethodSource("provideArguments") + void should_findEntitiesByVariableValueUsingSpecification( + VariableType variableType, + FilterOperator operator, + String filterValue, + List values, + Integer expectedSublistToIndex + ) { + VariableFilter filter = new VariableFilter(null, "name", variableType, filterValue, operator); + Specification specification = getSpecification(filter); + List variables = createVariablesWithValues(values); + List retrieved = variableRepository.findAll(specification); + + assertThat(retrieved).containsExactlyInAnyOrderElementsOf(variables.subList(0, expectedSublistToIndex)); + } + + @ParameterizedTest + @MethodSource("provideArgumentsThatShouldThrow") + void should_throw_InvalidDataAccessApiUsageException(VariableType variableType, FilterOperator operator) { + VariableFilter filter = new VariableFilter(null, "name", variableType, "", operator); + Specification specification = getSpecification(filter); + + assertThatThrownBy(() -> variableRepository.findAll(specification)) + .isInstanceOf(InvalidDataAccessApiUsageException.class) + .hasMessageContaining(variableType.name()) + .hasMessageContaining(operator.name()); + } + + private Specification getSpecification(VariableFilter filter) { + return new SpecificationSupport<>() { + @Override + public Predicate toPredicate( + Root root, + CriteriaQuery query, + CriteriaBuilder criteriaBuilder + ) { + return getVariableValueCondition(root.get(ProcessVariableEntity_.value), filter, criteriaBuilder); + } + }; + } + + private List createVariablesWithValues(List values) { + { + return values + .stream() + .map(value -> { + ProcessVariableEntity variable = new ProcessVariableEntity(); + variable.setValue(value); + variableRepository.save(variable); + return variable; + }) + .toList(); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceBuilder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceBuilder.java new file mode 100644 index 00000000000..8ec8965ee07 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceBuilder.java @@ -0,0 +1,128 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.util; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.ProcessVariableEntity; + +public class ProcessInstanceBuilder { + + private final ProcessInstanceEntity process; + private final Set taskBuffer = new HashSet<>(); + + private final VariableRepository variableRepository; + private final ProcessInstanceRepository processInstanceRepository; + + public ProcessInstanceBuilder( + VariableRepository variableRepository, + ProcessInstanceRepository processInstanceRepository + ) { + this.variableRepository = variableRepository; + this.processInstanceRepository = processInstanceRepository; + this.process = new ProcessInstanceEntity(); + this.process.setId(UUID.randomUUID().toString()); + this.process.setName(UUID.randomUUID().toString()); + this.withProcessDefinitionKey(UUID.randomUUID().toString()); + } + + public ProcessInstanceBuilder withName(String name) { + process.setName(name); + return this; + } + + public ProcessInstanceBuilder withAppName(String appName) { + process.setAppName(appName); + return this; + } + + public ProcessInstanceBuilder withProcessDefinitionKey(String processDefinitionKey) { + process.setProcessDefinitionKey(processDefinitionKey); + return this; + } + + public ProcessInstanceBuilder withAppVersion(String appVersion) { + process.setAppVersion(appVersion); + return this; + } + + public ProcessInstanceBuilder withLastModified(Date lastModified) { + process.setLastModified(lastModified); + return this; + } + + public ProcessInstanceBuilder withStartDate(Date startDate) { + process.setStartDate(startDate); + return this; + } + + public ProcessInstanceBuilder withCompletedDate(Date completedDate) { + process.setCompletedDate(completedDate); + return this; + } + + public ProcessInstanceBuilder withSuspendedDate(Date suspendedDate) { + process.setSuspendedDate(suspendedDate); + return this; + } + + public ProcessInstanceBuilder withVariables(QueryTestUtils.VariableInput... variables) { + process.setVariables( + Arrays + .stream(variables) + .map(variable -> { + ProcessVariableEntity processVariable = new ProcessVariableEntity(); + processVariable.setProcessInstanceId(process.getId()); + processVariable.setProcessDefinitionKey(process.getProcessDefinitionKey()); + processVariable.setName(variable.name()); + processVariable.setType(variable.type().name().toLowerCase()); + processVariable.setValue(variable.value()); + return processVariable; + }) + .collect(Collectors.toSet()) + ); + return this; + } + + public ProcessInstanceBuilder withTasks(TaskBuilder... tasks) { + taskBuffer.addAll(Arrays.asList(tasks)); + return this; + } + + public ProcessInstanceBuilder withInitiator(String initiator) { + process.setInitiator(initiator); + return this; + } + + public ProcessInstanceEntity buildAndSave() { + variableRepository.saveAll(process.getVariables()); + process.setTasks( + taskBuffer + .stream() + .map(builder -> builder.withParentProcess(process)) + .map(TaskBuilder::buildAndSave) + .collect(Collectors.toSet()) + ); + return processInstanceRepository.save(process); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceSearchRequestBuilder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceSearchRequestBuilder.java new file mode 100644 index 00000000000..b967652284a --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/ProcessInstanceSearchRequestBuilder.java @@ -0,0 +1,158 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.util; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import java.util.Date; +import java.util.Set; +import java.util.stream.Collectors; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.payload.CloudRuntimeEntitySort; +import org.activiti.cloud.services.query.rest.payload.ProcessInstanceSearchRequest; +import org.testcontainers.shaded.com.fasterxml.jackson.core.JsonProcessingException; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +public class ProcessInstanceSearchRequestBuilder { + + private Set names; + private Set initiators; + private Set appVersions; + private Date lastModifiedFrom; + private Date lastModifiedTo; + private Date startFrom; + private Date startTo; + private Date completedFrom; + private Date completedTo; + private Date suspendedFrom; + private Date suspendedTo; + private Set processVariableFilters; + private Set processVariableKeys; + private CloudRuntimeEntitySort sort; + + public ProcessInstanceSearchRequestBuilder withNames(String... names) { + this.names = Set.of(names); + return this; + } + + public ProcessInstanceSearchRequestBuilder withInitiators(String... initiators) { + this.initiators = Set.of(initiators); + return this; + } + + public ProcessInstanceSearchRequestBuilder withAppVersions(String... appVersions) { + this.appVersions = Set.of(appVersions); + return this; + } + + public ProcessInstanceSearchRequestBuilder withLastModifiedFrom(Date lastModifiedFrom) { + this.lastModifiedFrom = lastModifiedFrom; + return this; + } + + public ProcessInstanceSearchRequestBuilder withLastModifiedTo(Date lastModifiedTo) { + this.lastModifiedTo = lastModifiedTo; + return this; + } + + public ProcessInstanceSearchRequestBuilder withStartFrom(Date startFrom) { + this.startFrom = startFrom; + return this; + } + + public ProcessInstanceSearchRequestBuilder withStartTo(Date startTo) { + this.startTo = startTo; + return this; + } + + public ProcessInstanceSearchRequestBuilder withCompletedFrom(Date completedFrom) { + this.completedFrom = completedFrom; + return this; + } + + public ProcessInstanceSearchRequestBuilder withCompletedTo(Date completedTo) { + this.completedTo = completedTo; + return this; + } + + public ProcessInstanceSearchRequestBuilder withSuspendedFrom(Date suspendedFrom) { + this.suspendedFrom = suspendedFrom; + return this; + } + + public ProcessInstanceSearchRequestBuilder withSuspendedTo(Date suspendedTo) { + this.suspendedTo = suspendedTo; + return this; + } + + public ProcessInstanceSearchRequestBuilder withProcessVariableFilters(VariableFilter... processVariableFilters) { + this.processVariableFilters = Set.of(processVariableFilters); + return this; + } + + public ProcessInstanceSearchRequestBuilder withProcessVariableKeys(ProcessVariableKey... processVariableKeys) { + this.processVariableKeys = Set.of(processVariableKeys); + return this; + } + + public ProcessInstanceSearchRequestBuilder withSort(CloudRuntimeEntitySort sort) { + this.sort = sort; + return this; + } + + public ProcessInstanceSearchRequest build() { + if (processVariableFilters != null) { + Set keysFromFilters = processVariableFilters + .stream() + .map(variableFilter -> + new ProcessVariableKey(variableFilter.processDefinitionKey(), variableFilter.name()) + ) + .collect(Collectors.toSet()); + if (processVariableKeys == null) { + processVariableKeys = keysFromFilters; + } else { + processVariableKeys.addAll(keysFromFilters); + } + } + return new ProcessInstanceSearchRequest( + names, + initiators, + appVersions, + lastModifiedFrom, + lastModifiedTo, + startFrom, + startTo, + completedFrom, + completedTo, + suspendedFrom, + suspendedTo, + processVariableFilters, + processVariableKeys, + sort + ); + } + + public String buildJson() { + ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + return objectMapper.writeValueAsString(build()); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/QueryTestUtils.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/QueryTestUtils.java new file mode 100644 index 00000000000..108493f2ed1 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/QueryTestUtils.java @@ -0,0 +1,76 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.util; + +import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateUserRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.TaskVariableRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; +import org.activiti.cloud.services.query.rest.filter.VariableType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class QueryTestUtils { + + @Autowired + TaskRepository taskRepository; + + @Autowired + TaskVariableRepository taskVariableRepository; + + @Autowired + private ProcessInstanceRepository processInstanceRepository; + + @Autowired + private VariableRepository variableRepository; + + @Autowired + private TaskCandidateUserRepository taskCandidateUserRepository; + + @Autowired + private TaskCandidateGroupRepository taskCandidateGroupRepository; + + public void cleanUp() { + taskVariableRepository.deleteAll(); + taskRepository.deleteAll(); + taskCandidateUserRepository.deleteAll(); + taskCandidateGroupRepository.deleteAll(); + processInstanceRepository.deleteAll(); + variableRepository.deleteAll(); + } + + public ProcessInstanceBuilder buildProcessInstance() { + return new ProcessInstanceBuilder(variableRepository, processInstanceRepository); + } + + public TaskBuilder buildTask() { + return new TaskBuilder( + taskRepository, + taskVariableRepository, + taskCandidateUserRepository, + taskCandidateGroupRepository + ); + } + + public record VariableInput(String name, VariableType type, Object value) { + public String getValue() { + return value.toString(); + } + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/TaskBuilder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/TaskBuilder.java new file mode 100644 index 00000000000..8e2072b4e6a --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/TaskBuilder.java @@ -0,0 +1,183 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.util; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import org.activiti.api.task.model.Task; +import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateUserRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.TaskVariableRepository; +import org.activiti.cloud.services.query.model.ProcessInstanceEntity; +import org.activiti.cloud.services.query.model.TaskCandidateGroupEntity; +import org.activiti.cloud.services.query.model.TaskCandidateUserEntity; +import org.activiti.cloud.services.query.model.TaskEntity; +import org.activiti.cloud.services.query.model.TaskVariableEntity; + +public class TaskBuilder { + + private final TaskEntity task; + private final Set candidateUserIds = new HashSet<>(); + private final Set candidateGroupsIds = new HashSet<>(); + + private final TaskRepository taskRepository; + private final TaskVariableRepository taskVariableRepository; + private final TaskCandidateUserRepository taskCandidateUserRepository; + private final TaskCandidateGroupRepository taskCandidateGroupRepository; + + public TaskBuilder( + TaskRepository taskRepository, + TaskVariableRepository taskVariableRepository, + TaskCandidateUserRepository taskCandidateUserRepository, + TaskCandidateGroupRepository taskCandidateGroupRepository + ) { + this.taskRepository = taskRepository; + this.taskVariableRepository = taskVariableRepository; + this.taskCandidateUserRepository = taskCandidateUserRepository; + this.taskCandidateGroupRepository = taskCandidateGroupRepository; + this.task = new TaskEntity(); + this.task.setId(UUID.randomUUID().toString()); + this.task.setName(UUID.randomUUID().toString()); + } + + public TaskBuilder withName(String name) { + task.setName(name); + return this; + } + + public TaskBuilder withDescription(String description) { + task.setDescription(description); + return this; + } + + public TaskBuilder withParentTask(TaskEntity parentTask) { + task.setParentTaskId(parentTask.getId()); + return this; + } + + public TaskBuilder withPriority(Integer priority) { + task.setPriority(priority); + return this; + } + + public TaskBuilder withAssignee(String assignee) { + task.setAssignee(assignee); + return this; + } + + public TaskBuilder withStatus(Task.TaskStatus status) { + task.setStatus(status); + return this; + } + + public TaskBuilder withVariables(QueryTestUtils.VariableInput... variables) { + task.setVariables( + Arrays + .stream(variables) + .map(variable -> { + TaskVariableEntity taskVariable = new TaskVariableEntity(); + taskVariable.setName(variable.name()); + taskVariable.setType(variable.type().name().toLowerCase()); + taskVariable.setValue(variable.value()); + return taskVariable; + }) + .collect(Collectors.toSet()) + ); + return this; + } + + public TaskBuilder withParentProcess(ProcessInstanceEntity process) { + process.getTasks().add(task); + task.setProcessInstanceId(process.getId()); + task.setProcessDefinitionId(process.getProcessDefinitionId()); + task.setProcessDefinitionName(process.getProcessDefinitionName()); + task.setProcessVariables(process.getVariables()); + return this; + } + + public TaskBuilder withTaskCandidateUsers(String... users) { + candidateUserIds.addAll(Arrays.asList(users)); + return this; + } + + public TaskBuilder withTaskCandidateGroups(String... groups) { + candidateGroupsIds.addAll(Arrays.asList(groups)); + return this; + } + + public TaskBuilder withCompletedBy(String completedBy) { + task.setCompletedBy(completedBy); + return this; + } + + public TaskBuilder withCompletedDate(Date completedDate) { + task.setCompletedDate(completedDate); + return this; + } + + public TaskBuilder withCreatedDate(Date createdDate) { + task.setCreatedDate(createdDate); + return this; + } + + public TaskBuilder withDueDate(Date dueDate) { + task.setDueDate(dueDate); + return this; + } + + public TaskBuilder withClaimedDate(Date claimedDate) { + task.setClaimedDate(claimedDate); + return this; + } + + public TaskBuilder withLastModifiedDate(Date modifiedDate) { + task.setLastModified(modifiedDate); + return this; + } + + public TaskEntity buildAndSave() { + Set candidateUsers = + this.candidateUserIds.stream() + .map(user -> new TaskCandidateUserEntity(task.getId(), user)) + .collect(Collectors.toSet()); + taskCandidateUserRepository.saveAll(candidateUsers); + task.setTaskCandidateUsers(candidateUsers); + Set candidateGroups = + this.candidateGroupsIds.stream() + .map(group -> new TaskCandidateGroupEntity(task.getId(), group)) + .collect(Collectors.toSet()); + taskCandidateGroupRepository.saveAll(candidateGroups); + task.setTaskCandidateGroups(candidateGroups); + task + .getVariables() + .forEach(variable -> { + variable.setTaskId(task.getId()); + variable.setProcessInstanceId(task.getProcessInstanceId()); + }); + taskVariableRepository.saveAll(task.getVariables()); + return taskRepository.save(task); + } + + public TaskBuilder withProcessDefinitionName(String processDefinitionName) { + task.setProcessDefinitionName(processDefinitionName); + return this; + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/TaskSearchRequestBuilder.java b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/TaskSearchRequestBuilder.java new file mode 100644 index 00000000000..e6fa667be48 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-services-query/activiti-cloud-services-query-rest/src/test/java/org/activiti/cloud/services/query/util/TaskSearchRequestBuilder.java @@ -0,0 +1,214 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.query.util; + +import java.util.Date; +import java.util.Set; +import java.util.stream.Collectors; +import org.activiti.api.task.model.Task; +import org.activiti.cloud.services.query.model.ProcessVariableKey; +import org.activiti.cloud.services.query.rest.filter.VariableFilter; +import org.activiti.cloud.services.query.rest.payload.TaskSearchRequest; + +public class TaskSearchRequestBuilder { + + private boolean onlyStandalone; + private boolean onlyRoot; + private Set name; + private Set description; + private Set processDefinitionName; + private Set priority; + private Set status; + private Set completedBy; + private Set assignee; + private Date createdFrom; + private Date createdTo; + private Date lastModifiedFrom; + private Date lastModifiedTo; + private Date lastClaimedFrom; + private Date lastClaimedTo; + private Date dueDateFrom; + private Date dueDateTo; + private Date completedFrom; + private Date completedTo; + private Set candidateUserId; + private Set candidateGroupId; + private Set taskVariableFilters; + private Set processVariableFilters; + private Set processVariableKeys; + + public TaskSearchRequestBuilder onlyStandalone() { + this.onlyStandalone = true; + return this; + } + + public TaskSearchRequestBuilder onlyRoot() { + this.onlyRoot = true; + return this; + } + + public TaskSearchRequestBuilder withName(String... names) { + this.name = Set.of(names); + return this; + } + + public TaskSearchRequestBuilder withDescription(String... descriptions) { + this.description = Set.of(descriptions); + return this; + } + + public TaskSearchRequestBuilder withProcessDefinitionName(String... processDefinitionNames) { + this.processDefinitionName = Set.of(processDefinitionNames); + return this; + } + + public TaskSearchRequestBuilder withPriority(Integer... priorities) { + this.priority = Set.of(priorities); + return this; + } + + public TaskSearchRequestBuilder withStatus(Task.TaskStatus... statuses) { + this.status = Set.of(statuses); + return this; + } + + public TaskSearchRequestBuilder withCompletedBy(String... completedBy) { + this.completedBy = Set.of(completedBy); + return this; + } + + public TaskSearchRequestBuilder withAssignees(String... assignees) { + this.assignee = Set.of(assignees); + return this; + } + + public TaskSearchRequestBuilder withCreatedFrom(Date createdFrom) { + this.createdFrom = createdFrom; + return this; + } + + public TaskSearchRequestBuilder withCreatedTo(Date createdTo) { + this.createdTo = createdTo; + return this; + } + + public TaskSearchRequestBuilder withLastModifiedFrom(Date lastModifiedFrom) { + this.lastModifiedFrom = lastModifiedFrom; + return this; + } + + public TaskSearchRequestBuilder withLastModifiedTo(Date lastModifiedTo) { + this.lastModifiedTo = lastModifiedTo; + return this; + } + + public TaskSearchRequestBuilder withLastClaimedFrom(Date lastClaimedFrom) { + this.lastClaimedFrom = lastClaimedFrom; + return this; + } + + public TaskSearchRequestBuilder withLastClaimedTo(Date lastClaimedTo) { + this.lastClaimedTo = lastClaimedTo; + return this; + } + + public TaskSearchRequestBuilder withDueDateFrom(Date dueDateFrom) { + this.dueDateFrom = dueDateFrom; + return this; + } + + public TaskSearchRequestBuilder withDueDateTo(Date dueDateTo) { + this.dueDateTo = dueDateTo; + return this; + } + + public TaskSearchRequestBuilder withCompletedFrom(Date completedFrom) { + this.completedFrom = completedFrom; + return this; + } + + public TaskSearchRequestBuilder withCompletedTo(Date completedTo) { + this.completedTo = completedTo; + return this; + } + + public TaskSearchRequestBuilder withCandidateUserId(String... candidateUserIds) { + this.candidateUserId = Set.of(candidateUserIds); + return this; + } + + public TaskSearchRequestBuilder withCandidateGroupId(String... candidateGroupIds) { + this.candidateGroupId = Set.of(candidateGroupIds); + return this; + } + + public TaskSearchRequestBuilder withTaskVariableFilters(Set taskVariableFilters) { + this.taskVariableFilters = taskVariableFilters; + return this; + } + + public TaskSearchRequestBuilder withProcessVariableFilters(Set processVariableFilters) { + this.processVariableFilters = processVariableFilters; + return this; + } + + public TaskSearchRequestBuilder withProcessVariableKeys(Set processVariableKeys) { + this.processVariableKeys = processVariableKeys; + return this; + } + + public TaskSearchRequest build() { + if (processVariableFilters != null) { + Set keysFromFilters = processVariableFilters + .stream() + .map(variableFilter -> + new ProcessVariableKey(variableFilter.processDefinitionKey(), variableFilter.name()) + ) + .collect(Collectors.toSet()); + if (processVariableKeys == null) { + processVariableKeys = keysFromFilters; + } else { + processVariableKeys.addAll(keysFromFilters); + } + } + return new TaskSearchRequest( + onlyStandalone, + onlyRoot, + name, + description, + processDefinitionName, + priority, + status, + completedBy, + assignee, + createdFrom, + createdTo, + lastModifiedFrom, + lastModifiedTo, + lastClaimedFrom, + lastClaimedTo, + dueDateFrom, + dueDateTo, + completedFrom, + completedTo, + candidateUserId, + candidateGroupId, + taskVariableFilters, + processVariableFilters, + processVariableKeys + ); + } +} diff --git a/activiti-cloud-query-service/activiti-cloud-services-query/pom.xml b/activiti-cloud-query-service/activiti-cloud-services-query/pom.xml index 3e3bfb0a826..d99c67deab0 100644 --- a/activiti-cloud-query-service/activiti-cloud-services-query/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-services-query/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-query-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-query-dependencies activiti-cloud-services-query @@ -16,5 +16,7 @@ activiti-cloud-services-query-repo activiti-cloud-services-query-rest activiti-cloud-services-query-liquibase + activiti-cloud-services-query-consumer + activiti-cloud-services-query-events diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/pom.xml b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/pom.xml new file mode 100644 index 00000000000..fa1fd20d48c --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-query-dependencies + 8.7.0-SNAPSHOT + ../activiti-cloud-query-dependencies + + activiti-cloud-starter-query-consumer + Activiti Cloud Starter :: Query Events Consumer + + + org.activiti.cloud + activiti-cloud-services-metadata + + + org.activiti.cloud + activiti-cloud-services-monitoring + + + org.activiti.cloud + activiti-cloud-service-messaging-config + + + org.activiti.cloud + activiti-cloud-services-logging + + + org.activiti.cloud + activiti-cloud-services-query-consumer + + + org.activiti.cloud + activiti-cloud-services-query-liquibase + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.awaitility + awaitility + test + + + com.h2database + h2 + test + + + org.springframework.cloud + spring-cloud-stream-test-binder + test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + test + + + org.testcontainers + rabbitmq + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/java/org/activiti/cloud/starter/query/consumer/config/ActivitiQueryConsumerAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/java/org/activiti/cloud/starter/query/consumer/config/ActivitiQueryConsumerAutoConfiguration.java new file mode 100644 index 00000000000..e4f5ca400b7 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/java/org/activiti/cloud/starter/query/consumer/config/ActivitiQueryConsumerAutoConfiguration.java @@ -0,0 +1,23 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.starter.query.consumer.config; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.PropertySource; + +@AutoConfiguration +@PropertySource("classpath:query-messaging.properties") +public class ActivitiQueryConsumerAutoConfiguration {} diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..981f659c154 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.activiti.cloud.starter.query.consumer.config.ActivitiQueryConsumerAutoConfiguration diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/resources/metadata.properties b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/metadata.properties similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/resources/metadata.properties rename to activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/metadata.properties diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/resources/query-messaging.properties b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/query-messaging.properties similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/resources/query-messaging.properties rename to activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/main/resources/query-messaging.properties diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/test/java/org/activiti/cloud/starter/query/consumer/test/ActivitiQueryConsumerIT.java b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/test/java/org/activiti/cloud/starter/query/consumer/test/ActivitiQueryConsumerIT.java new file mode 100644 index 00000000000..24c68ba2075 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/test/java/org/activiti/cloud/starter/query/consumer/test/ActivitiQueryConsumerIT.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.starter.query.consumer.test; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.stream.binder.test.EnableTestBinder; + +@SpringBootTest +@SpringBootApplication +@EnableTestBinder +public class ActivitiQueryConsumerIT { + + @Test + void contextLoads() {} +} diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/test/resources/logback-test.xml b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e1f95399f50 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-consumer/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-rest/pom.xml b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/pom.xml new file mode 100644 index 00000000000..097fab87903 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + org.activiti.cloud + activiti-cloud-query-dependencies + 8.7.0-SNAPSHOT + ../activiti-cloud-query-dependencies + + + activiti-cloud-starter-query-rest + Activiti Cloud Starter :: Query Rest Api + + + + org.activiti.cloud + activiti-cloud-services-metadata + + + org.activiti + activiti-spring-security-policies + + + org.activiti.cloud + activiti-cloud-services-monitoring + + + org.activiti.cloud + activiti-cloud-services-logging + + + org.activiti.cloud + activiti-cloud-services-swagger + + + org.activiti.cloud + activiti-cloud-services-query-rest + + + org.activiti.cloud + activiti-cloud-services-query-liquibase + test + + + org.activiti.cloud + activiti-cloud-services-common-security-keycloak + + + org.activiti.cloud + activiti-cloud-services-common-identity-keycloak + + + org.activiti.cloud + activiti-cloud-service-error-handlers + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-hateoas + + + org.awaitility + awaitility + test + + + com.h2database + h2 + test + + + org.springframework.cloud + spring-cloud-stream-test-binder + test + + + org.activiti.cloud + activiti-cloud-services-test + test + + + org.activiti.cloud + activiti-cloud-services-test-containers + test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + test + + + org.testcontainers + rabbitmq + test + + + net.javacrumbs.json-unit + json-unit-assertj + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/ActivitiQueryAutoConfiguration.java b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/ActivitiQueryAutoConfiguration.java similarity index 88% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/ActivitiQueryAutoConfiguration.java rename to activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/ActivitiQueryAutoConfiguration.java index 003e18c4476..7bf61cf0b92 100644 --- a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/ActivitiQueryAutoConfiguration.java +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/ActivitiQueryAutoConfiguration.java @@ -17,9 +17,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.PropertySource; @AutoConfiguration @Import(QuerySwaggerConfig.class) -@PropertySource("classpath:query-messaging.properties") public class ActivitiQueryAutoConfiguration {} diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/EnableActivitiQuery.java b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/EnableActivitiQuery.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/EnableActivitiQuery.java rename to activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/EnableActivitiQuery.java diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/QuerySwaggerConfig.java b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/QuerySwaggerConfig.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/QuerySwaggerConfig.java rename to activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/QuerySwaggerConfig.java diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/VariableSearchWrapperMixin.java b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/VariableSearchWrapperMixin.java similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/java/org/activiti/cloud/starter/query/configuration/VariableSearchWrapperMixin.java rename to activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/java/org/activiti/cloud/starter/query/configuration/VariableSearchWrapperMixin.java diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports similarity index 100% rename from activiti-cloud-query-service/activiti-cloud-starter-query/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename to activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/resources/metadata.properties b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/resources/metadata.properties new file mode 100644 index 00000000000..c5c0886cb2e --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/main/resources/metadata.properties @@ -0,0 +1,5 @@ +activiti.cloud.service.type=query +spring.jackson.mapper.default-view-inclusion=true + +#disables zipkin reporting +spring.zipkin.enabled=false diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/test/java/org/activiti/cloud/starter/query/test/ActivitiCloudStarterQueryRestTest.java b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/test/java/org/activiti/cloud/starter/query/test/ActivitiCloudStarterQueryRestTest.java new file mode 100644 index 00000000000..462e7e38a58 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/test/java/org/activiti/cloud/starter/query/test/ActivitiCloudStarterQueryRestTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.starter.query.test; + +import org.activiti.cloud.starter.query.configuration.EnableActivitiQuery; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@SpringBootApplication +@EnableActivitiQuery +public class ActivitiCloudStarterQueryRestTest { + + @Test + void contextLoads() {} +} diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/test/resources/logback-test.xml b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e1f95399f50 --- /dev/null +++ b/activiti-cloud-query-service/activiti-cloud-starter-query-rest/src/test/resources/logback-test.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/pom.xml b/activiti-cloud-query-service/activiti-cloud-starter-query/pom.xml index 741850150e8..877b82c472e 100644 --- a/activiti-cloud-query-service/activiti-cloud-starter-query/pom.xml +++ b/activiti-cloud-query-service/activiti-cloud-starter-query/pom.xml @@ -6,11 +6,11 @@ org.activiti.cloud activiti-cloud-query-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-query-dependencies activiti-cloud-starter-query - Activiti Cloud Starter :: Query + Activiti Cloud Starter :: Query All In One org.activiti.cloud @@ -24,10 +24,6 @@ org.activiti.cloud activiti-cloud-services-monitoring - - org.activiti.cloud - activiti-cloud-service-messaging-config - org.activiti.cloud activiti-cloud-services-logging @@ -38,43 +34,19 @@ org.activiti.cloud - activiti-cloud-services-query-rest - - - org.activiti.cloud - activiti-cloud-services-query-liquibase + activiti-cloud-starter-query-consumer org.activiti.cloud - activiti-cloud-services-common-security-keycloak + activiti-cloud-starter-query-rest org.activiti.cloud - activiti-cloud-services-common-identity-keycloak + activiti-cloud-services-query-liquibase org.activiti.cloud - activiti-cloud-service-error-handlers - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-data-rest - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-hateoas + activiti-cloud-services-common-security-keycloak org.awaitility diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryProcessInstancesEntityIT.java b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryProcessInstancesEntityIT.java index 71de6df9e47..00973f176ec 100644 --- a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryProcessInstancesEntityIT.java +++ b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryProcessInstancesEntityIT.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Set; import java.util.TimeZone; import java.util.stream.Stream; import org.activiti.api.process.model.ProcessInstance; @@ -34,7 +35,9 @@ import org.activiti.api.runtime.model.impl.ActivitiErrorMessageImpl; import org.activiti.api.runtime.model.impl.ProcessInstanceImpl; import org.activiti.cloud.api.process.model.CloudProcessInstance; +import org.activiti.cloud.api.process.model.impl.events.CloudProcessCancelledEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessCreatedEventImpl; +import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessResumedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessStartedEventImpl; import org.activiti.cloud.api.process.model.impl.events.CloudProcessSuspendedEventImpl; @@ -43,6 +46,11 @@ import org.activiti.cloud.services.query.app.repository.BPMNActivityRepository; import org.activiti.cloud.services.query.app.repository.BPMNSequenceFlowRepository; import org.activiti.cloud.services.query.app.repository.ProcessInstanceRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateGroupRepository; +import org.activiti.cloud.services.query.app.repository.TaskCandidateUserRepository; +import org.activiti.cloud.services.query.app.repository.TaskRepository; +import org.activiti.cloud.services.query.app.repository.TaskVariableRepository; +import org.activiti.cloud.services.query.app.repository.VariableRepository; import org.activiti.cloud.services.query.model.AbstractVariableEntity; import org.activiti.cloud.services.query.model.BPMNActivityEntity; import org.activiti.cloud.services.query.model.BPMNSequenceFlowEntity; @@ -59,6 +67,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -109,6 +118,21 @@ public class QueryProcessInstancesEntityIT { @Autowired private SubscribableChannel errorChannel; + @Autowired + private TaskRepository taskRepository; + + @Autowired + private TaskVariableRepository taskVariableRepository; + + @Autowired + private TaskCandidateGroupRepository taskCandidateGroupRepository; + + @Autowired + private TaskCandidateUserRepository taskCandidateUserRepository; + + @Autowired + private VariableRepository variableRepository; + private EventsAggregator eventsAggregator; private ProcessInstanceEventContainedBuilder processInstanceBuilder; @@ -130,7 +154,12 @@ public void setUp() { public void tearDown() { sequenceFlowRepository.deleteAll(); activityRepository.deleteAll(); + taskVariableRepository.deleteAll(); + taskRepository.deleteAll(); + variableRepository.deleteAll(); processInstanceRepository.deleteAll(); + taskCandidateGroupRepository.deleteAll(); + taskCandidateUserRepository.deleteAll(); } @Test @@ -259,6 +288,77 @@ public void shouldGetAdminProcessInfo() { }); } + @Test + public void shouldDeleteProcessInfo() { + //given + ProcessInstance process = processInstanceBuilder.startSimpleProcessInstance("simple"); + + var candidateUserTask = taskEventBuilder.aTaskWithUserCandidate("userCandidate", "testuser", process); + var candidateGroupTask = taskEventBuilder.aTaskWithGroupCandidate("groupCandidate", "testgroup", process); + + variableBuilder.aCreatedVariable("foo", "bar").onProcessInstance(process); + variableBuilder.aCreatedVariable("baz", "qux").onTask(candidateGroupTask); + variableBuilder.aCreatedVariable("quux", "bax").onTask(candidateUserTask); + + eventsAggregator.sendAll(); + + await() + .untilAsserted(() -> { + identityTokenProducer.withTestUser("hradmin"); + + ResponseEntity responseEntity = testRestTemplate.exchange( + ADMIN_PROC_URL + "/" + process.getId(), + HttpMethod.GET, + identityTokenProducer.entityWithAuthorizationHeader(), + new ParameterizedTypeReference<>() {} + ); + //then + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(responseEntity.getBody()).isNotNull(); + assertThat(responseEntity.getBody().getId()).isNotNull(); + + ProcessInstance responseProcess = responseEntity.getBody(); + assertThat(responseProcess.getId()).isEqualTo(process.getId()); + + assertThat(taskRepository.findAll()).isNotEmpty(); + assertThat(taskVariableRepository.findAll()).isNotEmpty(); + assertThat(activityRepository.findAll()).isNotEmpty(); + assertThat(sequenceFlowRepository.findAll()).isNotEmpty(); + assertThat(variableRepository.findAll()).isNotEmpty(); + assertThat(processInstanceRepository.findAll()).isNotEmpty(); + assertThat(taskCandidateGroupRepository.findAll()).isNotEmpty(); + assertThat(taskCandidateUserRepository.findAll()).isNotEmpty(); + + eventsAggregator.addEvents(new CloudProcessCancelledEventImpl(responseProcess)); + eventsAggregator.addEvents(new CloudProcessDeletedEventImpl(responseProcess)); + }); + + eventsAggregator.sendAll(); + + await() + .untilAsserted(() -> { + identityTokenProducer.withTestUser("hradmin"); + + ResponseEntity responseEntity = testRestTemplate.exchange( + ADMIN_PROC_URL + "/" + process.getId(), + HttpMethod.GET, + identityTokenProducer.entityWithAuthorizationHeader(), + new ParameterizedTypeReference<>() {} + ); + //then + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + + assertThat(taskRepository.findAll()).isEmpty(); + assertThat(taskVariableRepository.findAll()).isEmpty(); + assertThat(activityRepository.findAll()).isEmpty(); + assertThat(sequenceFlowRepository.findAll()).isEmpty(); + assertThat(variableRepository.findAll()).isEmpty(); + assertThat(processInstanceRepository.findAll()).isEmpty(); + assertThat(taskCandidateGroupRepository.findAll()).isEmpty(); + assertThat(taskCandidateUserRepository.findAll()).isEmpty(); + }); + } + @Test public void shouldGetProcessDefinitionVersion() { //given @@ -417,6 +517,59 @@ public void shouldGetProcessInstancesAsAdmin() { }); } + @ParameterizedTest + @CsvSource( + { + "status=COMPLETED, 1", + "status=RUNNING, 2", + "status=COMPLETED&status=RUNNING, 1;2", + "status=CREATED&status=RUNNING, 2", + } + ) + public void shouldGetProcessInstancesAppVersionsAsAdmin(String queryParameters, String expectedResult) { + //given + processInstanceBuilder.aCompletedProcessInstanceWithAppVersion("Process for filter", "1"); + processInstanceBuilder.aRunningProcessInstanceWithAppVersion("Process", "2"); + + eventsAggregator.sendAll(); + + identityTokenProducer.withTestUser("hradmin"); + await() + .untilAsserted(() -> { + ResponseEntity> responseEntity = testRestTemplate.exchange( + ADMIN_PROC_URL + "/appVersions?" + queryParameters, + HttpMethod.GET, + identityTokenProducer.entityWithAuthorizationHeader(), + new ParameterizedTypeReference<>() {} + ); + //then + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(responseEntity.getBody()).isInstanceOf(Set.class).containsExactly(expectedResult.split(";")); + }); + } + + @Test + public void shouldGetProcessInstancesEmptyAppVersionsAsAdmin() { + //given + processInstanceBuilder.aCompletedProcessInstanceWithAppVersion("Process for filter", "1"); + + eventsAggregator.sendAll(); + + identityTokenProducer.withTestUser("hradmin"); + await() + .untilAsserted(() -> { + ResponseEntity> responseEntity = testRestTemplate.exchange( + ADMIN_PROC_URL + "/appVersions?status=CREATED", + HttpMethod.GET, + identityTokenProducer.entityWithAuthorizationHeader(), + new ParameterizedTypeReference<>() {} + ); + //then + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(responseEntity.getBody()).isInstanceOf(Set.class).isEmpty(); + }); + } + private ResponseEntity> executeRequestGetProcInstances() { return testRestTemplate.exchange( PROC_URL, diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryTasksIT.java b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryTasksIT.java index 641212d9b95..00de48694fd 100644 --- a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryTasksIT.java +++ b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/java/org/activiti/cloud/starter/tests/QueryTasksIT.java @@ -2651,21 +2651,6 @@ void should_migrateTaskProcessVariables() throws Exception { taskProcessVariableCount = processVariablesMigrationHelper.getTaskProcessVariableCount(task.getId()); assertThat(taskProcessVariableCount).isEqualTo(0); - await() - .untilAsserted(() -> { - //when - Collection retrievedTasks = executeRequestGetTasksWithProcessVariables( - "varAProcessDefinitionKey/varAName" - ) - .getBody() - .getContent(); - - //then - assertThat(retrievedTasks) - .extracting(Task::getName, tasks -> tasks.getProcessVariables().size()) - .containsExactly(tuple("Task", 0)); - }); - processVariablesMigrationHelper.migrateTaskProcessVariableData(); taskProcessVariableCount = processVariablesMigrationHelper.getTaskProcessVariableCount(task.getId()); assertThat(taskProcessVariableCount).isEqualTo(2); diff --git a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json index ac0ade52c47..17522698c8a 100644 --- a/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json +++ b/activiti-cloud-query-service/activiti-cloud-starter-query/src/test/resources/swagger-expected.json @@ -10,6 +10,216 @@ } ], "paths": { + "/v1/tasks/search": { + "post": { + "tags": [ + "task-controller" + ], + "summary": "Search tasks", + "operationId": "searchTasks", + "parameters": [ + { + "name": "maxItems", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "skipCount", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskSearchRequest_General" + } + } + }, + "required": true + }, + "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentQueryCloudTask_General" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentQueryCloudTask_General" + } + } + } + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "oauth": [] + } + ] + } + }, + "/v1/process-instances/search": { + "post": { + "tags": [ + "process-instance-controller" + ], + "summary": "Search process instances", + "operationId": "searchProcessInstances", + "parameters": [ + { + "name": "maxItems", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "skipCount", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProcessInstanceSearchRequest_ProcessVariables" + } + } + }, + "required": true + }, + "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + } + } + } + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "oauth": [] + } + ] + } + }, "/admin/v1/tasks": { "get": { "tags": [ @@ -379,6 +589,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -406,9 +636,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -760,6 +987,26 @@ } }, "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -787,9 +1034,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -1085,6 +1329,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -1112,9 +1376,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -1124,10 +1385,115 @@ ] } }, - "/admin/v1/process-instances": { - "get": { + "/admin/v1/tasks/search": { + "post": { "tags": [ - "process-instance-admin-controller" + "task-admin-controller" + ], + "summary": "Search tasks", + "operationId": "searchTasks", + "parameters": [ + { + "name": "maxItems", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "skipCount", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TaskSearchRequest_General" + } + } + }, + "required": true + }, + "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentQueryCloudTask_General" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentQueryCloudTask_General" + } + } + } + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "oauth": [] + } + ] + } + }, + "/admin/v1/process-instances": { + "get": { + "tags": [ + "process-instance-admin-controller" ], "summary": "Find process instances", "operationId": "findAllWithVariablesAdmin", @@ -1386,6 +1752,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -1413,9 +1799,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -1680,6 +2063,26 @@ } }, "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -1707,9 +2110,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -1936,6 +2336,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -1963,9 +2383,111 @@ }, "401": { "description": "Unauthorized" + } + }, + "security": [ + { + "oauth": [] + } + ] + } + }, + "/admin/v1/process-instances/search": { + "post": { + "tags": [ + "process-instance-admin-controller" + ], + "summary": "Search process instances", + "operationId": "searchProcessInstances", + "parameters": [ + { + "name": "maxItems", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "skipCount", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "style": "form", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProcessInstanceSearchRequest_ProcessVariables" + } + } }, + "required": true + }, + "responses": { "404": { - "description": "Not Found" + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentCloudProcessInstance_ProcessVariables" + } + } + } + }, + "401": { + "description": "Unauthorized" } }, "security": [ @@ -2344,8 +2866,8 @@ } ], "responses": { - "403": { - "description": "Forbidden", + "404": { + "description": "Not Found", "content": { "application/json": { "schema": { @@ -2354,12 +2876,32 @@ } } }, - "200": { - "description": "OK", + "400": { + "description": "Bad Request", "content": { - "application/hal+json": { + "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponseContentQueryCloudTask_ProcessVariables" + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/ListResponseContentQueryCloudTask_ProcessVariables" } }, "application/json": { @@ -2371,9 +2913,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -2445,6 +2984,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -2472,9 +3031,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -2502,6 +3058,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -2529,9 +3105,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -2559,6 +3132,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -2592,9 +3185,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -2622,6 +3212,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -2655,9 +3265,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -2929,6 +3536,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -2956,9 +3583,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -2986,6 +3610,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3013,9 +3657,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3094,6 +3735,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3121,9 +3782,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3194,6 +3852,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3221,9 +3899,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3492,6 +4167,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3519,9 +4214,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3549,6 +4241,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3571,9 +4283,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3686,6 +4395,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3713,9 +4442,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3743,6 +4469,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3765,9 +4511,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3837,8 +4580,8 @@ } ], "responses": { - "403": { - "description": "Forbidden", + "404": { + "description": "Not Found", "content": { "application/json": { "schema": { @@ -3847,8 +4590,28 @@ } } }, - "200": { - "description": "OK", + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", "content": { "application/hal+json": { "schema": { @@ -3864,9 +4627,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3938,6 +4698,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -3965,9 +4745,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -3995,6 +4772,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4022,9 +4819,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4052,6 +4846,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4085,9 +4899,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4115,6 +4926,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4148,9 +4979,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4199,6 +5027,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4226,9 +5074,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4256,6 +5101,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4283,9 +5148,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4313,6 +5175,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4340,9 +5222,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4370,6 +5249,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4397,9 +5296,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4478,6 +5374,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4505,9 +5421,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4564,6 +5477,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4591,9 +5524,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4650,6 +5580,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4677,9 +5627,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4707,6 +5654,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4729,9 +5696,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4741,16 +5705,299 @@ ] } }, - "/admin/v1/process-definitions": { + "/admin/v1/process-instances/appVersions": { "get": { "tags": [ - "process-definition-admin-controller" + "process-instance-admin-controller" ], - "summary": "Find all Process Admin", - "operationId": "findAllProcessAdmin", + "summary": "Find application versions for process instances", + "operationId": "findProcessAppVersions", "parameters": [ { - "name": "maxItems", + "name": "initiator", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "processDefinitionName", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "lastModifiedTo", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "serviceTasks", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "processDefinitionKey", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "startTo", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "completedTo", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "id", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "tasks", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "lastModifiedFrom", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "processDefinitionId", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "variables", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "sequenceFlows", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "startFrom", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "completedFrom", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "completedDate", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "parentId", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "suspendedFrom", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "activities", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "name", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "businessKey", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "lastModified", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "suspendedDate", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "startDate", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "processDefinitionVersion", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string", + "enum": [ + "CREATED", + "RUNNING", + "SUSPENDED", + "CANCELLED", + "COMPLETED" + ] + } + }, + { + "name": "suspendedTo", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + } + ], + "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + } + }, + "application/json": { + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "oauth": [] + } + ] + } + }, + "/admin/v1/process-definitions": { + "get": { + "tags": [ + "process-definition-admin-controller" + ], + "summary": "Find all Process Admin", + "operationId": "findAllProcessAdmin", + "parameters": [ + { + "name": "maxItems", "in": "query", "required": false, "style": "form", @@ -4844,6 +6091,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4871,9 +6138,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4901,6 +6165,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -4923,9 +6207,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -4995,6 +6276,26 @@ } ], "responses": { + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EntryResponseContentActivitiErrorMessage" + } + } + } + }, "403": { "description": "Forbidden", "content": { @@ -5022,9 +6323,6 @@ }, "401": { "description": "Unauthorized" - }, - "404": { - "description": "Not Found" } }, "security": [ @@ -5059,60 +6357,208 @@ } } }, - "TasksQueryBody": { - "title": "TasksQueryBody", + "ProcessVariableKey_General": { + "title": "ProcessVariableKey_General", "type": "object", "properties": { - "variableKeys": { - "type": "array", - "items": { - "type": "string" - } - }, - "standalone": { - "type": "boolean" + "processDefinitionKey": { + "type": "string" }, - "rootTasksOnly": { - "type": "boolean" + "variableName": { + "type": "string" } } }, - "FilterProvider": { - "title": "FilterProvider", - "type": "object" - }, - "MappingJacksonValue": { - "title": "MappingJacksonValue", + "TaskSearchRequest_General": { + "title": "TaskSearchRequest_General", "type": "object", "properties": { - "value": { - "type": "object" + "onlyStandalone": { + "type": "boolean" + }, + "onlyRoot": { + "type": "boolean" + }, + "name": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "processDefinitionName": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "priority": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + "status": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string", + "enum": [ + "CREATED", + "ASSIGNED", + "SUSPENDED", + "COMPLETED", + "CANCELLED", + "DELETED" + ] + } + }, + "completedBy": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "assignee": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "createdFrom": { + "type": "string", + "format": "date-time" + }, + "createdTo": { + "type": "string", + "format": "date-time" + }, + "lastModifiedFrom": { + "type": "string", + "format": "date-time" + }, + "lastModifiedTo": { + "type": "string", + "format": "date-time" + }, + "lastClaimedFrom": { + "type": "string", + "format": "date-time" + }, + "lastClaimedTo": { + "type": "string", + "format": "date-time" + }, + "dueDateFrom": { + "type": "string", + "format": "date-time" + }, + "dueDateTo": { + "type": "string", + "format": "date-time" + }, + "completedFrom": { + "type": "string", + "format": "date-time" + }, + "completedTo": { + "type": "string", + "format": "date-time" + }, + "candidateUserId": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "candidateGroupId": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "taskVariableFilters": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/VariableFilter_General" + } + }, + "processVariableFilters": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/VariableFilter_General" + } }, - "filters": { - "$ref": "#/components/schemas/FilterProvider" + "processVariableKeys": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/ProcessVariableKey_General" + } } } }, - "ProcessInstanceQueryBody": { - "title": "ProcessInstanceQueryBody", + "VariableFilter_General": { + "title": "VariableFilter_General", "type": "object", "properties": { - "variableKeys": { - "type": "array", - "items": { - "type": "string" - } + "processDefinitionKey": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "string", + "integer", + "bigdecimal", + "boolean", + "date", + "datetime" + ] + }, + "value": { + "type": "string" + }, + "operator": { + "type": "string", + "enum": [ + "eq", + "like", + "gt", + "gte", + "lt", + "lte" + ] } } }, - "CloudVariableInstance_ProcessVariables": { - "title": "CloudVariableInstance_ProcessVariables", + "CloudVariableInstance_General": { + "title": "CloudVariableInstance_General", "type": "object", "properties": { - "serviceName": { + "appName": { "type": "string" }, - "appName": { + "serviceName": { "type": "string" }, "serviceType": { @@ -5147,41 +6593,41 @@ } } }, - "EntriesResponseContentQueryCloudTask_ProcessVariables": { - "title": "EntriesResponseContentQueryCloudTask_ProcessVariables", + "EntriesResponseContentQueryCloudTask_General": { + "title": "EntriesResponseContentQueryCloudTask_General", "type": "object", "properties": { "entries": { "type": "array", "items": { - "$ref": "#/components/schemas/EntryResponseContentQueryCloudTask_ProcessVariables" + "$ref": "#/components/schemas/EntryResponseContentQueryCloudTask_General" } }, "pagination": { - "$ref": "#/components/schemas/PaginationMetadata_ProcessVariables" + "$ref": "#/components/schemas/PaginationMetadata_General" } } }, - "EntryResponseContentQueryCloudTask_ProcessVariables": { - "title": "EntryResponseContentQueryCloudTask_ProcessVariables", + "EntryResponseContentQueryCloudTask_General": { + "title": "EntryResponseContentQueryCloudTask_General", "type": "object", "properties": { "entry": { - "$ref": "#/components/schemas/QueryCloudTask_ProcessVariables" + "$ref": "#/components/schemas/QueryCloudTask_General" } } }, - "ListResponseContentQueryCloudTask_ProcessVariables": { - "title": "ListResponseContentQueryCloudTask_ProcessVariables", + "ListResponseContentQueryCloudTask_General": { + "title": "ListResponseContentQueryCloudTask_General", "type": "object", "properties": { "list": { - "$ref": "#/components/schemas/EntriesResponseContentQueryCloudTask_ProcessVariables" + "$ref": "#/components/schemas/EntriesResponseContentQueryCloudTask_General" } } }, - "PaginationMetadata_ProcessVariables": { - "title": "PaginationMetadata_ProcessVariables", + "PaginationMetadata_General": { + "title": "PaginationMetadata_General", "type": "object", "properties": { "skipCount": { @@ -5205,8 +6651,8 @@ } } }, - "QueryCloudTask_ProcessVariables": { - "title": "QueryCloudTask_ProcessVariables", + "QueryCloudTask_General": { + "title": "QueryCloudTask_General", "type": "object", "properties": { "permissions": { @@ -5221,22 +6667,22 @@ ] } }, - "processDefinitionName": { - "type": "string" - }, "processVariables": { "uniqueItems": true, "type": "array", "items": { - "$ref": "#/components/schemas/CloudVariableInstance_ProcessVariables" + "$ref": "#/components/schemas/CloudVariableInstance_General" } }, - "serviceName": { + "processDefinitionName": { "type": "string" }, "appName": { "type": "string" }, + "serviceName": { + "type": "string" + }, "serviceType": { "type": "string" }, @@ -5269,9 +6715,32 @@ "standalone": { "type": "boolean" }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" + "businessKey": { + "type": "string" + }, + "assignee": { + "type": "string" + }, + "formKey": { + "type": "string" + }, + "createdDate": { + "type": "string", + "format": "date-time" + }, + "dueDate": { + "type": "string", + "format": "date-time" + }, + "claimedDate": { + "type": "string", + "format": "date-time" + }, + "completedBy": { + "type": "string" + }, + "description": { + "type": "string" }, "status": { "type": "string", @@ -5284,71 +6753,206 @@ "DELETED" ] }, - "description": { + "candidateUsers": { + "type": "array", + "items": { + "type": "string" + } + }, + "candidateGroups": { + "type": "array", + "items": { + "type": "string" + } + }, + "parentTaskId": { "type": "string" }, - "businessKey": { + "taskDefinitionKey": { "type": "string" }, - "completedBy": { + "processDefinitionId": { "type": "string" }, - "createdDate": { - "type": "string", - "format": "date-time" + "processInstanceId": { + "type": "string" }, - "dueDate": { + "completedDate": { "type": "string", "format": "date-time" }, - "assignee": { + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + } + } + }, + "CloudRuntimeEntitySort_ProcessVariables": { + "title": "CloudRuntimeEntitySort_ProcessVariables", + "type": "object", + "properties": { + "field": { "type": "string" }, - "claimedDate": { + "direction": { "type": "string", - "format": "date-time" + "enum": [ + "ASC", + "DESC" + ] }, - "formKey": { + "isProcessVariable": { + "type": "boolean" + }, + "processDefinitionKey": { "type": "string" }, - "candidateUsers": { + "type": { + "type": "string", + "enum": [ + "string", + "integer", + "bigdecimal", + "boolean", + "date", + "datetime" + ] + } + } + }, + "ProcessInstanceSearchRequest_ProcessVariables": { + "title": "ProcessInstanceSearchRequest_ProcessVariables", + "type": "object", + "properties": { + "name": { + "uniqueItems": true, "type": "array", "items": { "type": "string" } }, - "candidateGroups": { + "initiator": { + "uniqueItems": true, "type": "array", "items": { "type": "string" } }, - "completedDate": { + "appVersion": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + }, + "lastModifiedFrom": { "type": "string", "format": "date-time" }, - "parentTaskId": { + "lastModifiedTo": { + "type": "string", + "format": "date-time" + }, + "startFrom": { + "type": "string", + "format": "date-time" + }, + "startTo": { + "type": "string", + "format": "date-time" + }, + "completedFrom": { + "type": "string", + "format": "date-time" + }, + "completedTo": { + "type": "string", + "format": "date-time" + }, + "suspendedFrom": { + "type": "string", + "format": "date-time" + }, + "suspendedTo": { + "type": "string", + "format": "date-time" + }, + "processVariableFilters": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/VariableFilter_ProcessVariables" + } + }, + "processVariableKeys": { + "uniqueItems": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/ProcessVariableKey_ProcessVariables" + } + }, + "sort": { + "$ref": "#/components/schemas/CloudRuntimeEntitySort_ProcessVariables" + } + } + }, + "ProcessVariableKey_ProcessVariables": { + "title": "ProcessVariableKey_ProcessVariables", + "type": "object", + "properties": { + "processDefinitionKey": { "type": "string" }, - "taskDefinitionKey": { + "variableName": { + "type": "string" + } + } + }, + "VariableFilter_ProcessVariables": { + "title": "VariableFilter_ProcessVariables", + "type": "object", + "properties": { + "processDefinitionKey": { "type": "string" }, - "processInstanceId": { + "name": { "type": "string" }, - "processDefinitionId": { + "type": { + "type": "string", + "enum": [ + "string", + "integer", + "bigdecimal", + "boolean", + "date", + "datetime" + ] + }, + "value": { "type": "string" + }, + "operator": { + "type": "string", + "enum": [ + "eq", + "like", + "gt", + "gte", + "lt", + "lte" + ] } } }, - "CloudVariableInstance": { - "title": "CloudVariableInstance", + "CloudProcessInstance_ProcessVariables": { + "title": "CloudProcessInstance_ProcessVariables", "type": "object", "properties": { - "serviceName": { + "appName": { "type": "string" }, - "appName": { + "serviceName": { "type": "string" }, "serviceType": { @@ -5360,64 +6964,92 @@ "serviceVersion": { "type": "string" }, - "appVersion": { + "appVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "startDate": { + "type": "string", + "format": "date-time" + }, + "businessKey": { + "type": "string" + }, + "initiator": { "type": "string" }, - "name": { + "parentId": { "type": "string" }, - "value": { - "type": "object" + "status": { + "type": "string", + "enum": [ + "CREATED", + "RUNNING", + "SUSPENDED", + "CANCELLED", + "COMPLETED" + ] }, - "type": { + "processDefinitionId": { "type": "string" }, - "taskVariable": { - "type": "boolean" + "completedDate": { + "type": "string", + "format": "date-time" }, - "taskId": { + "processDefinitionName": { "type": "string" }, - "processInstanceId": { + "processDefinitionKey": { "type": "string" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" } } }, - "EntriesResponseContentCloudVariableInstance": { - "title": "EntriesResponseContentCloudVariableInstance", + "EntriesResponseContentCloudProcessInstance_ProcessVariables": { + "title": "EntriesResponseContentCloudProcessInstance_ProcessVariables", "type": "object", "properties": { "entries": { "type": "array", "items": { - "$ref": "#/components/schemas/EntryResponseContentCloudVariableInstance" + "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_ProcessVariables" } }, "pagination": { - "$ref": "#/components/schemas/PaginationMetadata" + "$ref": "#/components/schemas/PaginationMetadata_ProcessVariables" } } }, - "EntryResponseContentCloudVariableInstance": { - "title": "EntryResponseContentCloudVariableInstance", + "EntryResponseContentCloudProcessInstance_ProcessVariables": { + "title": "EntryResponseContentCloudProcessInstance_ProcessVariables", "type": "object", "properties": { "entry": { - "$ref": "#/components/schemas/CloudVariableInstance" + "$ref": "#/components/schemas/CloudProcessInstance_ProcessVariables" } } }, - "ListResponseContentCloudVariableInstance": { - "title": "ListResponseContentCloudVariableInstance", + "ListResponseContentCloudProcessInstance_ProcessVariables": { + "title": "ListResponseContentCloudProcessInstance_ProcessVariables", "type": "object", "properties": { "list": { - "$ref": "#/components/schemas/EntriesResponseContentCloudVariableInstance" + "$ref": "#/components/schemas/EntriesResponseContentCloudProcessInstance_ProcessVariables" } } }, - "PaginationMetadata": { - "title": "PaginationMetadata", + "PaginationMetadata_ProcessVariables": { + "title": "PaginationMetadata_ProcessVariables", "type": "object", "properties": { "skipCount": { @@ -5441,16 +7073,62 @@ } } }, - "CloudVariableInstance_General": { - "title": "CloudVariableInstance_General", + "TasksQueryBody": { + "title": "TasksQueryBody", "type": "object", "properties": { - "serviceName": { - "type": "string" + "variableKeys": { + "type": "array", + "items": { + "type": "string" + } + }, + "standalone": { + "type": "boolean" + }, + "rootTasksOnly": { + "type": "boolean" + } + } + }, + "FilterProvider": { + "title": "FilterProvider", + "type": "object" + }, + "MappingJacksonValue": { + "title": "MappingJacksonValue", + "type": "object", + "properties": { + "value": { + "type": "object" }, + "filters": { + "$ref": "#/components/schemas/FilterProvider" + } + } + }, + "ProcessInstanceQueryBody": { + "title": "ProcessInstanceQueryBody", + "type": "object", + "properties": { + "variableKeys": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "CloudVariableInstance_ProcessVariables": { + "title": "CloudVariableInstance_ProcessVariables", + "type": "object", + "properties": { "appName": { "type": "string" }, + "serviceName": { + "type": "string" + }, "serviceType": { "type": "string" }, @@ -5483,17 +7161,41 @@ } } }, - "EntryResponseContentQueryCloudTask_General": { - "title": "EntryResponseContentQueryCloudTask_General", + "EntriesResponseContentQueryCloudTask_ProcessVariables": { + "title": "EntriesResponseContentQueryCloudTask_ProcessVariables", + "type": "object", + "properties": { + "entries": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EntryResponseContentQueryCloudTask_ProcessVariables" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata_ProcessVariables" + } + } + }, + "EntryResponseContentQueryCloudTask_ProcessVariables": { + "title": "EntryResponseContentQueryCloudTask_ProcessVariables", "type": "object", "properties": { "entry": { - "$ref": "#/components/schemas/QueryCloudTask_General" + "$ref": "#/components/schemas/QueryCloudTask_ProcessVariables" } } }, - "QueryCloudTask_General": { - "title": "QueryCloudTask_General", + "ListResponseContentQueryCloudTask_ProcessVariables": { + "title": "ListResponseContentQueryCloudTask_ProcessVariables", + "type": "object", + "properties": { + "list": { + "$ref": "#/components/schemas/EntriesResponseContentQueryCloudTask_ProcessVariables" + } + } + }, + "QueryCloudTask_ProcessVariables": { + "title": "QueryCloudTask_ProcessVariables", "type": "object", "properties": { "permissions": { @@ -5508,22 +7210,22 @@ ] } }, - "processDefinitionName": { - "type": "string" - }, "processVariables": { "uniqueItems": true, "type": "array", "items": { - "$ref": "#/components/schemas/CloudVariableInstance_General" + "$ref": "#/components/schemas/CloudVariableInstance_ProcessVariables" } }, - "serviceName": { + "processDefinitionName": { "type": "string" }, "appName": { "type": "string" }, + "serviceName": { + "type": "string" + }, "serviceType": { "type": "string" }, @@ -5556,28 +7258,13 @@ "standalone": { "type": "boolean" }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string", - "enum": [ - "CREATED", - "ASSIGNED", - "SUSPENDED", - "COMPLETED", - "CANCELLED", - "DELETED" - ] - }, - "description": { + "businessKey": { "type": "string" }, - "businessKey": { + "assignee": { "type": "string" }, - "completedBy": { + "formKey": { "type": "string" }, "createdDate": { @@ -5588,16 +7275,27 @@ "type": "string", "format": "date-time" }, - "assignee": { - "type": "string" - }, "claimedDate": { "type": "string", "format": "date-time" }, - "formKey": { + "completedBy": { + "type": "string" + }, + "description": { "type": "string" }, + "status": { + "type": "string", + "enum": [ + "CREATED", + "ASSIGNED", + "SUSPENDED", + "COMPLETED", + "CANCELLED", + "DELETED" + ] + }, "candidateUsers": { "type": "array", "items": { @@ -5610,32 +7308,36 @@ "type": "string" } }, - "completedDate": { - "type": "string", - "format": "date-time" - }, "parentTaskId": { "type": "string" }, "taskDefinitionKey": { "type": "string" }, - "processInstanceId": { + "processDefinitionId": { "type": "string" }, - "processDefinitionId": { + "processInstanceId": { "type": "string" + }, + "completedDate": { + "type": "string", + "format": "date-time" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" } } }, - "CloudProcessInstance_ProcessVariables": { - "title": "CloudProcessInstance_ProcessVariables", + "CloudVariableInstance": { + "title": "CloudVariableInstance", "type": "object", "properties": { - "serviceName": { + "appName": { "type": "string" }, - "appName": { + "serviceName": { "type": "string" }, "serviceType": { @@ -5653,81 +7355,78 @@ "name": { "type": "string" }, - "id": { - "type": "string" - }, - "processDefinitionKey": { - "type": "string" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "processDefinitionName": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "CREATED", - "RUNNING", - "SUSPENDED", - "CANCELLED", - "COMPLETED" - ] - }, - "parentId": { - "type": "string" - }, - "initiator": { - "type": "string" + "value": { + "type": "object" }, - "businessKey": { + "type": { "type": "string" }, - "startDate": { - "type": "string", - "format": "date-time" + "taskVariable": { + "type": "boolean" }, - "completedDate": { - "type": "string", - "format": "date-time" + "taskId": { + "type": "string" }, - "processDefinitionId": { + "processInstanceId": { "type": "string" } } }, - "EntriesResponseContentCloudProcessInstance_ProcessVariables": { - "title": "EntriesResponseContentCloudProcessInstance_ProcessVariables", + "EntriesResponseContentCloudVariableInstance": { + "title": "EntriesResponseContentCloudVariableInstance", "type": "object", "properties": { "entries": { "type": "array", "items": { - "$ref": "#/components/schemas/EntryResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/EntryResponseContentCloudVariableInstance" } }, "pagination": { - "$ref": "#/components/schemas/PaginationMetadata_ProcessVariables" + "$ref": "#/components/schemas/PaginationMetadata" } } }, - "EntryResponseContentCloudProcessInstance_ProcessVariables": { - "title": "EntryResponseContentCloudProcessInstance_ProcessVariables", + "EntryResponseContentCloudVariableInstance": { + "title": "EntryResponseContentCloudVariableInstance", "type": "object", "properties": { "entry": { - "$ref": "#/components/schemas/CloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/CloudVariableInstance" } } }, - "ListResponseContentCloudProcessInstance_ProcessVariables": { - "title": "ListResponseContentCloudProcessInstance_ProcessVariables", + "ListResponseContentCloudVariableInstance": { + "title": "ListResponseContentCloudVariableInstance", "type": "object", "properties": { "list": { - "$ref": "#/components/schemas/EntriesResponseContentCloudProcessInstance_ProcessVariables" + "$ref": "#/components/schemas/EntriesResponseContentCloudVariableInstance" + } + } + }, + "PaginationMetadata": { + "title": "PaginationMetadata", + "type": "object", + "properties": { + "skipCount": { + "type": "integer", + "format": "int64" + }, + "maxItems": { + "type": "integer", + "format": "int64" + }, + "count": { + "type": "integer", + "format": "int64" + }, + "hasMoreItems": { + "type": "boolean" + }, + "totalItems": { + "type": "integer", + "format": "int64" } } }, @@ -5735,10 +7434,10 @@ "title": "CloudProcessInstance_General", "type": "object", "properties": { - "serviceName": { + "appName": { "type": "string" }, - "appName": { + "serviceName": { "type": "string" }, "serviceType": { @@ -5759,14 +7458,17 @@ "id": { "type": "string" }, - "processDefinitionKey": { + "startDate": { + "type": "string", + "format": "date-time" + }, + "businessKey": { "type": "string" }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" + "initiator": { + "type": "string" }, - "processDefinitionName": { + "parentId": { "type": "string" }, "status": { @@ -5779,25 +7481,22 @@ "COMPLETED" ] }, - "parentId": { - "type": "string" - }, - "initiator": { - "type": "string" - }, - "businessKey": { + "processDefinitionId": { "type": "string" }, - "startDate": { - "type": "string", - "format": "date-time" - }, "completedDate": { "type": "string", "format": "date-time" }, - "processDefinitionId": { + "processDefinitionName": { "type": "string" + }, + "processDefinitionKey": { + "type": "string" + }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" } } }, @@ -5834,39 +7533,14 @@ } } }, - "PaginationMetadata_General": { - "title": "PaginationMetadata_General", - "type": "object", - "properties": { - "skipCount": { - "type": "integer", - "format": "int64" - }, - "maxItems": { - "type": "integer", - "format": "int64" - }, - "count": { - "type": "integer", - "format": "int64" - }, - "hasMoreItems": { - "type": "boolean" - }, - "totalItems": { - "type": "integer", - "format": "int64" - } - } - }, "CloudProcessDefinition": { "title": "CloudProcessDefinition", "type": "object", "properties": { - "serviceName": { + "appName": { "type": "string" }, - "appName": { + "serviceName": { "type": "string" }, "serviceType": { @@ -5894,14 +7568,14 @@ "type": "integer", "format": "int32" }, - "description": { - "type": "string" - }, "formKey": { "type": "string" }, "category": { "type": "string" + }, + "description": { + "type": "string" } } }, @@ -5993,12 +7667,12 @@ "id": { "type": "string" }, - "processDefinitionKey": { - "type": "string" + "startedDate": { + "type": "string", + "format": "date-time" }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" + "businessKey": { + "type": "string" }, "status": { "type": "string", @@ -6009,10 +7683,7 @@ "ERROR" ] }, - "businessKey": { - "type": "string" - }, - "startedDate": { + "cancelledDate": { "type": "string", "format": "date-time" }, @@ -6020,16 +7691,19 @@ "type": "string", "format": "date-time" }, - "cancelledDate": { - "type": "string", - "format": "date-time" - }, - "serviceName": { + "processDefinitionKey": { "type": "string" }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, "appName": { "type": "string" }, + "serviceName": { + "type": "string" + }, "serviceType": { "type": "string" }, @@ -6045,19 +7719,19 @@ "executionId": { "type": "string" }, - "activityType": { + "activityName": { "type": "string" }, - "activityName": { + "activityType": { "type": "string" }, "elementId": { "type": "string" }, - "processInstanceId": { + "processDefinitionId": { "type": "string" }, - "processDefinitionId": { + "processInstanceId": { "type": "string" } } @@ -6102,17 +7776,6 @@ "errorMessage": { "type": "string" }, - "status": { - "type": "string", - "enum": [ - "INTEGRATION_REQUESTED", - "INTEGRATION_RESULT_RECEIVED", - "INTEGRATION_ERROR_RECEIVED" - ] - }, - "errorCode": { - "type": "string" - }, "requestDate": { "type": "string", "format": "date-time" @@ -6125,6 +7788,20 @@ "type": "string", "format": "date-time" }, + "errorCode": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "INTEGRATION_REQUESTED", + "INTEGRATION_RESULT_RECEIVED", + "INTEGRATION_ERROR_RECEIVED" + ] + }, + "errorClassName": { + "type": "string" + }, "stackTraceElements": { "type": "array", "items": { @@ -6158,70 +7835,67 @@ } } }, - "errorClassName": { - "type": "string" - }, "id": { "type": "string" }, - "processDefinitionKey": { - "type": "string" - }, - "processDefinitionVersion": { - "type": "integer", - "format": "int32" - }, - "rootProcessInstanceId": { - "type": "string" - }, - "parentProcessInstanceId": { - "type": "string" - }, "clientId": { "type": "string" }, "clientName": { "type": "string" }, - "businessKey": { - "type": "string" - }, "executionId": { "type": "string" }, "clientType": { "type": "string" }, + "businessKey": { + "type": "string" + }, "appVersion": { "type": "string" }, - "outBoundVariables": { + "connectorType": { + "type": "string" + }, + "inBoundVariables": { "type": "object", "additionalProperties": { "type": "object" } }, - "connectorType": { - "type": "string" - }, - "inBoundVariables": { + "outBoundVariables": { "type": "object", "additionalProperties": { "type": "object" } }, + "processDefinitionId": { + "type": "string" + }, "processInstanceId": { "type": "string" }, - "processDefinitionId": { + "rootProcessInstanceId": { "type": "string" }, - "serviceName": { + "processDefinitionKey": { + "type": "string" + }, + "parentProcessInstanceId": { "type": "string" }, + "processDefinitionVersion": { + "type": "integer", + "format": "int32" + }, "appName": { "type": "string" }, + "serviceName": { + "type": "string" + }, "serviceType": { "type": "string" }, @@ -6241,30 +7915,6 @@ "$ref": "#/components/schemas/CloudIntegrationContext" } } - }, - "EntriesResponseContentQueryCloudTask_General": { - "title": "EntriesResponseContentQueryCloudTask_General", - "type": "object", - "properties": { - "entries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EntryResponseContentQueryCloudTask_General" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMetadata_General" - } - } - }, - "ListResponseContentQueryCloudTask_General": { - "title": "ListResponseContentQueryCloudTask_General", - "type": "object", - "properties": { - "list": { - "$ref": "#/components/schemas/EntriesResponseContentQueryCloudTask_General" - } - } } } }, diff --git a/activiti-cloud-query-service/pom.xml b/activiti-cloud-query-service/pom.xml index 4eb6b87783e..d597c37ce39 100644 --- a/activiti-cloud-query-service/pom.xml +++ b/activiti-cloud-query-service/pom.xml @@ -5,20 +5,21 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-query-service-parent Activiti Cloud Query :: Parent pom - activiti-cloud-query-dependencies activiti-cloud-services-query activiti-cloud-starter-query + activiti-cloud-starter-query-consumer + activiti-cloud-starter-query-rest - 8.5.0-alpha.4 + 8.7.0-alpha.27 diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-runtime-bundle-dependencies/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-runtime-bundle-dependencies/pom.xml index 85ebaee6b3c..ed33eea0607 100755 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-runtime-bundle-dependencies/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-runtime-bundle-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-runtime-bundle-service-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-runtime-bundle-dependencies pom diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-runtime-bundle-rest-client/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-runtime-bundle-rest-client/pom.xml index ac12c120352..c2d12abf691 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-runtime-bundle-rest-client/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-runtime-bundle-rest-client/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-services-runtime-bundle org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-runtime-bundle-rest-client Activiti Cloud Services :: REST API Clients diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-api/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-api/pom.xml index cb00c4ec652..eef7ec61e4c 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-api/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-api/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-api Activiti Cloud Services :: APIs diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/pom.xml index cf2d4df85e5..57543f44778 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-connectors Activiti Cloud Services :: Connectors diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/behavior/MQServiceTaskBehavior.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/behavior/MQServiceTaskBehavior.java index 8d78144e39c..6968bf3fa68 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/behavior/MQServiceTaskBehavior.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/behavior/MQServiceTaskBehavior.java @@ -22,8 +22,8 @@ import org.activiti.cloud.services.events.configuration.RuntimeBundleProperties; import org.activiti.cloud.services.events.listeners.ProcessEngineEventsAggregator; import org.activiti.engine.delegate.DelegateExecution; -import org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; -import org.activiti.engine.impl.delegate.TriggerableActivityBehavior; +import org.activiti.engine.impl.bpmn.behavior.DelegateExecutionFunction; +import org.activiti.engine.impl.bpmn.behavior.DelegateExecutionOutcome; import org.activiti.engine.impl.persistence.entity.integration.IntegrationContextEntity; import org.activiti.engine.impl.persistence.entity.integration.IntegrationContextManager; import org.activiti.runtime.api.connector.DefaultServiceTaskBehavior; @@ -31,7 +31,7 @@ import org.activiti.services.connectors.IntegrationRequestSender; import org.activiti.services.connectors.channel.IntegrationRequestBuilder; -public class MQServiceTaskBehavior extends AbstractBpmnActivityBehavior implements TriggerableActivityBehavior { +public class MQServiceTaskBehavior implements DelegateExecutionFunction { private final IntegrationContextManager integrationContextManager; private final IntegrationContextBuilder integrationContextBuilder; @@ -60,18 +60,20 @@ public MQServiceTaskBehavior( } @Override - public void execute(DelegateExecution execution) { + public DelegateExecutionOutcome apply(DelegateExecution execution) { if (defaultServiceTaskBehavior.hasConnectorBean(execution)) { // use de default implementation -> directly call a bean - defaultServiceTaskBehavior.execute(execution); - } else { - IntegrationContextEntity integrationContextEntity = storeIntegrationContext(execution); + return defaultServiceTaskBehavior.apply(execution); + } - IntegrationContext integrationContext = integrationContextBuilder.from(integrationContextEntity, execution); - sendIntegrationRequest(integrationContext); + IntegrationContext integrationContext = integrationContextBuilder.from( + storeIntegrationContext(execution), + execution + ); + sendIntegrationRequest(integrationContext); + aggregateCloudIntegrationRequestedEvent(integrationContext); - aggregateCloudIntegrationRequestedEvent(integrationContext); - } + return DelegateExecutionOutcome.WAIT_FOR_TRIGGER; } private void aggregateCloudIntegrationRequestedEvent(IntegrationContext integrationContext) { @@ -102,9 +104,4 @@ private IntegrationContextEntity buildIntegrationContext(DelegateExecution execu integrationContext.setCreatedDate(new Date()); return integrationContext; } - - @Override - public void trigger(DelegateExecution execution, String signalEvent, Object signalData) { - leave(execution); - } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/channel/IntegrationRequestReplayer.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/channel/IntegrationRequestReplayer.java index d487eb7b358..1004b177127 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/channel/IntegrationRequestReplayer.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/main/java/org/activiti/services/connectors/channel/IntegrationRequestReplayer.java @@ -51,7 +51,7 @@ public void replay(String executionId, String flowNodeId) { ExecutionEntity execution = (ExecutionEntity) executions.get(0); managementService.executeCommand( (Command) commandContext -> { - mqServiceTaskBehavior.execute(execution); + mqServiceTaskBehavior.apply(execution); return null; } ); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/test/java/org/activiti/services/connectors/behavior/MQServiceTaskBehaviorTest.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/test/java/org/activiti/services/connectors/behavior/MQServiceTaskBehaviorTest.java index 387bca25a3d..8198e08838a 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/test/java/org/activiti/services/connectors/behavior/MQServiceTaskBehaviorTest.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-connectors/src/test/java/org/activiti/services/connectors/behavior/MQServiceTaskBehaviorTest.java @@ -19,7 +19,6 @@ import static org.activiti.test.Assertions.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -120,10 +119,10 @@ public void executeShouldDelegateToDefaultBehaviourWhenBeanIsAvailable() { given(defaultServiceTaskBehavior.hasConnectorBean(execution)).willReturn(true); //when - behavior.execute(execution); + behavior.apply(execution); //then - verify(defaultServiceTaskBehavior).execute(execution); + verify(defaultServiceTaskBehavior).apply(execution); } @Test @@ -147,7 +146,7 @@ public void executeShouldStoreTheIntegrationContextAndPublishASpringEvent() { when(runtimeBundleProperties.getEventsProperties().isIntegrationAuditEventsEnabled()).thenReturn(true); //when - behavior.execute(execution); + behavior.apply(execution); //then ((ExecutionEntity) execution).getProcessInstance(); @@ -165,17 +164,4 @@ public void executeShouldStoreTheIntegrationContextAndPublishASpringEvent() { verify(processEngineEventsAggregator).add(any(CloudIntegrationRequestedEvent.class)); } - - @Test - public void triggerShouldCallLeave() { - //given - DelegateExecution execution = mock(DelegateExecution.class); - doNothing().when(behavior).leave(execution); - - //when - behavior.trigger(execution, null, null); - - //then - verify(behavior).leave(execution); - } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-core/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-core/pom.xml index 5e68ddf80a7..a5df2ea8d24 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-core/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-core/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-core Activiti Cloud Services :: Core diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/pom.xml index 9745b5bda8c..91f6e8c1cff 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-events Activiti Cloud Services :: Events diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/configuration/CloudEventsAutoConfiguration.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/configuration/CloudEventsAutoConfiguration.java index 66fdf002039..18c935d223b 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/configuration/CloudEventsAutoConfiguration.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/configuration/CloudEventsAutoConfiguration.java @@ -74,6 +74,7 @@ import org.activiti.cloud.services.events.message.ExecutionContextMessageBuilderFactory; import org.activiti.cloud.services.events.message.RuntimeBundleMessageBuilderFactory; import org.activiti.cloud.services.events.services.CloudProcessDeletedService; +import org.activiti.engine.ManagementService; import org.activiti.engine.RuntimeService; import org.activiti.engine.impl.context.Context; import org.activiti.spring.process.CachingProcessExtensionService; @@ -593,14 +594,9 @@ public CloudApplicationDeployedProducer cloudApplicationDeployedProducer( @Bean @ConditionalOnMissingBean public CloudProcessDeletedService cloudProcessDeletedProducer( - ProcessEngineChannels processEngineChannels, - RuntimeBundleMessageBuilderFactory runtimeBundleMessageBuilderFactory, - RuntimeBundleInfoAppender runtimeBundleInfoAppender + ManagementService managementService, + ProcessEngineEventsAggregator processEngineEventsAggregator ) { - return new CloudProcessDeletedService( - processEngineChannels, - runtimeBundleMessageBuilderFactory, - runtimeBundleInfoAppender - ); + return new CloudProcessDeletedService(managementService, processEngineEventsAggregator); } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/CloudProcessDeletedService.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/CloudProcessDeletedService.java index 0d6d861df77..dd82a33b940 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/CloudProcessDeletedService.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/CloudProcessDeletedService.java @@ -15,50 +15,31 @@ */ package org.activiti.cloud.services.events.services; -import java.util.Arrays; -import java.util.List; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; -import org.activiti.cloud.api.process.model.impl.CloudProcessInstanceImpl; -import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; -import org.activiti.cloud.services.events.ProcessEngineChannels; -import org.activiti.cloud.services.events.converter.RuntimeBundleInfoAppender; -import org.activiti.cloud.services.events.message.RuntimeBundleMessageBuilderFactory; +import org.activiti.cloud.services.events.listeners.ProcessEngineEventsAggregator; +import org.activiti.engine.ManagementService; public class CloudProcessDeletedService { - private final ProcessEngineChannels producer; - private final RuntimeBundleMessageBuilderFactory runtimeBundleMessageBuilderFactory; - private final RuntimeBundleInfoAppender runtimeBundleInfoAppender; + private final ManagementService managementService; + private final ProcessEngineEventsAggregator processEngineEventsAggregator; public CloudProcessDeletedService( - ProcessEngineChannels producer, - RuntimeBundleMessageBuilderFactory runtimeBundleMessageBuilderFactory, - RuntimeBundleInfoAppender runtimeBundleInfoAppender + ManagementService managementService, + ProcessEngineEventsAggregator processEngineEventsAggregator ) { - this.producer = producer; - this.runtimeBundleMessageBuilderFactory = runtimeBundleMessageBuilderFactory; - this.runtimeBundleInfoAppender = runtimeBundleInfoAppender; + this.managementService = managementService; + this.processEngineEventsAggregator = processEngineEventsAggregator; } - public void sendDeleteEvent(String processInstanceId) { - sendEvent(buildProcessInstance(processInstanceId)); - } - - protected void sendEvent(ProcessInstance processInstance) { - producer - .auditProducer() - .send(runtimeBundleMessageBuilderFactory.create().withPayload(buildEvents(processInstance)).build()); + public void delete(String processInstanceId) { + managementService.executeCommand( + new DeleteCloudProcessInstanceCmd(processInstanceId, processEngineEventsAggregator) + ); } - protected List> buildEvents(ProcessInstance processInstance) { - CloudProcessDeletedEventImpl event = new CloudProcessDeletedEventImpl(processInstance); - return Arrays.asList(runtimeBundleInfoAppender.appendRuntimeBundleInfoTo(event)); - } - - protected ProcessInstance buildProcessInstance(String processInstanceId) { - CloudProcessInstanceImpl processInstance = new CloudProcessInstanceImpl(); - processInstance.setId(processInstanceId); - return processInstance; + public void sendDeleteEvent(String processInstanceId) { + managementService.executeCommand( + new SendDeleteCloudProcessInstanceEventCmd(processInstanceId, processEngineEventsAggregator) + ); } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/DeleteCloudProcessInstanceCmd.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/DeleteCloudProcessInstanceCmd.java new file mode 100644 index 00000000000..e67f4d31cc6 --- /dev/null +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/DeleteCloudProcessInstanceCmd.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.events.services; + +import java.util.ArrayList; +import java.util.List; +import org.activiti.cloud.services.events.listeners.ProcessEngineEventsAggregator; +import org.activiti.engine.impl.cmd.DeleteProcessInstanceCmd; +import org.activiti.engine.impl.interceptor.Command; +import org.activiti.engine.impl.interceptor.CommandContext; + +class DeleteCloudProcessInstanceCmd implements Command { + + private final List> commands = new ArrayList<>(); + + public DeleteCloudProcessInstanceCmd( + String processInstanceId, + ProcessEngineEventsAggregator processEngineEventsAggregator + ) { + commands.add(new DeleteProcessInstanceCmd(processInstanceId, null)); + commands.add(new SendDeleteCloudProcessInstanceEventCmd(processInstanceId, processEngineEventsAggregator)); + } + + @Override + public Void execute(CommandContext commandContext) { + commands.forEach(command -> command.execute(commandContext)); + + return null; + } +} diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/SendDeleteCloudProcessInstanceEventCmd.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/SendDeleteCloudProcessInstanceEventCmd.java new file mode 100644 index 00000000000..72a27a930d9 --- /dev/null +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/main/java/org/activiti/cloud/services/events/services/SendDeleteCloudProcessInstanceEventCmd.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.events.services; + +import org.activiti.cloud.api.process.model.impl.CloudProcessInstanceImpl; +import org.activiti.cloud.api.process.model.impl.events.CloudProcessDeletedEventImpl; +import org.activiti.cloud.services.events.listeners.ProcessEngineEventsAggregator; +import org.activiti.engine.impl.interceptor.Command; +import org.activiti.engine.impl.interceptor.CommandContext; + +class SendDeleteCloudProcessInstanceEventCmd implements Command { + + private final ProcessEngineEventsAggregator processEngineEventsAggregator; + private final String processInstanceId; + + public SendDeleteCloudProcessInstanceEventCmd( + String processInstanceId, + ProcessEngineEventsAggregator processEngineEventsAggregator + ) { + this.processInstanceId = processInstanceId; + this.processEngineEventsAggregator = processEngineEventsAggregator; + } + + @Override + public Void execute(CommandContext commandContext) { + CloudProcessInstanceImpl processInstance = new CloudProcessInstanceImpl(); + processInstance.setId(processInstanceId); + + processEngineEventsAggregator.add(new CloudProcessDeletedEventImpl(processInstance)); + + return null; + } +} diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/test/java/org/activiti/cloud/services/events/services/CloudProcessDeletedServiceTest.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/test/java/org/activiti/cloud/services/events/services/CloudProcessDeletedServiceTest.java index a4dbf76ca1b..1d00ba56c20 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/test/java/org/activiti/cloud/services/events/services/CloudProcessDeletedServiceTest.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-events/src/test/java/org/activiti/cloud/services/events/services/CloudProcessDeletedServiceTest.java @@ -16,20 +16,15 @@ package org.activiti.cloud.services.events.services; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import org.activiti.cloud.services.events.ProcessEngineChannels; -import org.activiti.cloud.services.events.configuration.RuntimeBundleProperties; -import org.activiti.cloud.services.events.converter.RuntimeBundleInfoAppender; -import org.activiti.cloud.services.events.message.RuntimeBundleMessageBuilderFactory; +import org.activiti.cloud.services.events.listeners.ProcessEngineEventsAggregator; +import org.activiti.engine.ManagementService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.messaging.MessageChannel; @ExtendWith(MockitoExtension.class) public class CloudProcessDeletedServiceTest { @@ -37,42 +32,35 @@ public class CloudProcessDeletedServiceTest { private CloudProcessDeletedService cloudProcessDeletedService; @Mock - private RuntimeBundleProperties properties; + private ManagementService managementService; @Mock - private ProcessEngineChannels producer; - - @Mock - private MessageChannel auditProducer; + private ProcessEngineEventsAggregator processEngineEventsAggregator; @BeforeEach public void setUp() { - RuntimeBundleInfoAppender runtimeBundleInfoAppender = new RuntimeBundleInfoAppender(properties); - RuntimeBundleMessageBuilderFactory runtimeBundleMessageBuilderFactory = new RuntimeBundleMessageBuilderFactory( - properties - ); - cloudProcessDeletedService = - new CloudProcessDeletedService(producer, runtimeBundleMessageBuilderFactory, runtimeBundleInfoAppender); - } - - private void setProperties() { - when(producer.auditProducer()).thenReturn(auditProducer); - when(properties.getAppName()).thenReturn("an"); - when(properties.getServiceName()).thenReturn("sn"); - when(properties.getServiceFullName()).thenReturn("sfn"); - when(properties.getServiceType()).thenReturn("st"); - when(properties.getServiceVersion()).thenReturn("sv"); + cloudProcessDeletedService = new CloudProcessDeletedService(managementService, processEngineEventsAggregator); } @Test public void should_sendDeleteEvent() { //given - setProperties(); //when cloudProcessDeletedService.sendDeleteEvent("1"); //then - verify(auditProducer, times(1)).send(any()); + verify(managementService).executeCommand(any(SendDeleteCloudProcessInstanceEventCmd.class)); + } + + @Test + public void should_deleteProcessInstance() { + //given + + //when + cloudProcessDeletedService.delete("1"); + + //then + verify(managementService).executeCommand(any(DeleteCloudProcessInstanceCmd.class)); } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-identity-basic/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-identity-basic/pom.xml index 1a235841f86..7841f0b728d 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-identity-basic/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-identity-basic/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-identity-basic Activiti Cloud Services :: Identity Basic Integration diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-job-executor/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-job-executor/pom.xml index 5af4c46e620..b889a8b5e31 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-job-executor/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-job-executor/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-job-executor diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/pom.xml index 3fe3e19d4cb..e527cceff93 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-rest-api Activiti Cloud Services :: REST APIs diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessDefinitionController.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessDefinitionController.java index 19677469621..5e524e72fd9 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessDefinitionController.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessDefinitionController.java @@ -70,4 +70,12 @@ Map getProcessModelStaticValuesMappingForStartEvent( description = "Enter the id to get process model static values mapping for start event" ) @PathVariable(value = "id") String id ); + + @GetMapping(value = "/v1/process-definitions/{id}/constant-values", produces = "application/json") + @ResponseBody + Map getProcessModelConstantValuesForStartEvent( + @Parameter(description = "Enter the id to get process model constant values for start event") @PathVariable( + value = "id" + ) String id + ); } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessInstanceAdminController.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessInstanceAdminController.java index a7b2a6fba9f..3d546513f7c 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessInstanceAdminController.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-api/src/main/java/org/activiti/cloud/services/rest/api/ProcessInstanceAdminController.java @@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; @RequestMapping( value = "/admin/v1/process-instances", @@ -68,8 +69,13 @@ EntityModel deleteProcessInstance( @RequestMapping(value = "/{processInstanceId}/destroy", method = RequestMethod.DELETE) ResponseEntity destroyProcessInstance( @Parameter( - description = "Enter the processInstanceId to delete a process instance" - ) @PathVariable String processInstanceId + description = "Enter the processInstanceId to destroy a process instance" + ) @PathVariable String processInstanceId, + @Parameter(description = "Enable force delete if the process is still running") @RequestParam( + value = "force", + required = false, + defaultValue = "false" + ) boolean force ); @RequestMapping(value = "/{processInstanceId}", method = RequestMethod.PUT) diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/pom.xml index 49cd902c418..b19e0b76ec2 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-rest-impl Activiti Cloud Services :: REST Impl diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImpl.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImpl.java index 5f17bdfcf31..bd12a5a8469 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImpl.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImpl.java @@ -61,6 +61,7 @@ import org.activiti.spring.process.CachingProcessExtensionService; import org.activiti.spring.process.model.Extension; import org.activiti.spring.process.model.Mapping.SourceMappingType; +import org.activiti.spring.process.model.ProcessConstantsMapping; import org.activiti.spring.process.model.ProcessVariablesMapping; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; @@ -178,13 +179,60 @@ public String getProcessDiagram(@PathVariable String id) { @Override public Map getProcessModelStaticValuesMappingForStartEvent(String id) { - checkUserCanReadProcessDefinition(id); + Map result = new HashMap<>(); + ExtensionsStartEventId extensionsStartEventId = getProcessExtensionsForStartEvent(id, true); + if ( + extensionsStartEventId != null && + extensionsStartEventId.extensions() != null && + extensionsStartEventId.id() != null + ) { + ProcessVariablesMapping startEventMappings = extensionsStartEventId + .extensions() + .getMappings() + .get(extensionsStartEventId.id()); + + if (startEventMappings != null) { + startEventMappings + .getInputs() + .forEach((input, mapping) -> { + if (SourceMappingType.VALUE.equals(mapping.getType())) { + result.put(input, mapping.getValue()); + } + }); + } + } + return result; + } + + @Override + public Map getProcessModelConstantValuesForStartEvent(String id) { Map result = new HashMap<>(); + ExtensionsStartEventId extensionsStartEventId = getProcessExtensionsForStartEvent(id, false); + if ( + extensionsStartEventId != null && + extensionsStartEventId.extensions() != null && + extensionsStartEventId.id() != null + ) { + ProcessConstantsMapping startEventConstants = extensionsStartEventId + .extensions() + .getConstantForFlowElement(extensionsStartEventId.id()); + + if (startEventConstants != null) { + startEventConstants.keySet().forEach(key -> result.put(key, startEventConstants.get(key).getValue())); + } + } + + return result; + } + + private ExtensionsStartEventId getProcessExtensionsForStartEvent(String id, boolean formRequired) { + checkUserCanReadProcessDefinition(id); + BpmnModel bpmnModel = repositoryService.getBpmnModel(id); Process process = bpmnModel.getMainProcess(); - if (bpmnModel.getStartFormKey(process.getId()) != null) { + if (!formRequired || bpmnModel.getStartFormKey(process.getId()) != null) { Optional startEvent = process .getFlowElements() .stream() @@ -192,23 +240,15 @@ public Map getProcessModelStaticValuesMappingForStartEvent(Strin .findFirst(); if (startEvent.isPresent()) { - Extension extensions = cachingProcessExtensionService.getExtensionsForId(id); - if (extensions != null) { - ProcessVariablesMapping startEventMappings = extensions.getMappings().get(startEvent.get().getId()); - - if (startEventMappings != null) { - startEventMappings - .getInputs() - .forEach((input, mapping) -> { - if (SourceMappingType.VALUE.equals(mapping.getType())) { - result.put(input, mapping.getValue()); - } - }); - } - } + return new ExtensionsStartEventId( + startEvent.get().getId(), + cachingProcessExtensionService.getExtensionsForId(id) + ); } } - return result; + return null; } + + private record ExtensionsStartEventId(String id, Extension extensions) {} } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImpl.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImpl.java index 94005f950f5..bb47ceacaa8 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImpl.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImpl.java @@ -148,11 +148,16 @@ public EntityModel deleteProcessInstance(@PathVariable Str } @Override - public ResponseEntity destroyProcessInstance(@PathVariable String processInstanceId) { + public ResponseEntity destroyProcessInstance(@PathVariable String processInstanceId, boolean force) { try { ProcessInstance processInstance = processAdminRuntime.processInstance(processInstanceId); if (processInstance != null && !deleteStatuses.contains(processInstance.getStatus())) { - throw new IllegalStateException(String.format(DELETE_PROCESS_NOT_ALLOWED, processInstanceId)); + if (force) { + cloudProcessDeletedService.delete(processInstanceId); + return ResponseEntity.status(HttpStatus.OK).build(); + } else { + throw new IllegalStateException(String.format(DELETE_PROCESS_NOT_ALLOWED, processInstanceId)); + } } } catch (NotFoundException e) { LOGGER.debug("Process Instance " + processInstanceId + " not found. Sending PROCESS_DELETE event."); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/RuntimeBundleExceptionHandler.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/RuntimeBundleExceptionHandler.java index 3ffda51b567..a1480f75165 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/RuntimeBundleExceptionHandler.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/main/java/org/activiti/cloud/services/rest/controllers/RuntimeBundleExceptionHandler.java @@ -90,10 +90,10 @@ public EntityModel handleAppException( } @ExceptionHandler(ActivitiException.class) - @ResponseStatus(INTERNAL_SERVER_ERROR) + @ResponseStatus(BAD_REQUEST) public EntityModel handleAppException(ActivitiException ex, HttpServletResponse response) { response.setContentType(APPLICATION_JSON_VALUE); - return EntityModel.of(new ActivitiErrorMessageImpl(INTERNAL_SERVER_ERROR.value(), ex.getMessage())); + return EntityModel.of(new ActivitiErrorMessageImpl(BAD_REQUEST.value(), ex.getMessage())); } @ExceptionHandler(ActivitiIllegalArgumentException.class) diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupAdminControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupAdminControllerImplIT.java index 788b7295253..6653a1f2a64 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupAdminControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupAdminControllerImplIT.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.List; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; import org.activiti.api.runtime.shared.security.SecurityContextPrincipalProvider; @@ -38,6 +39,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -101,6 +103,12 @@ class CandidateGroupAdminControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(pageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupControllerImplIT.java index 2bc10ca69d6..c1278d8ef90 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateGroupControllerImplIT.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.List; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; import org.activiti.api.runtime.shared.security.SecurityContextPrincipalProvider; @@ -38,6 +39,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -101,6 +103,12 @@ class CandidateGroupControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(springPageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserAdminControllerIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserAdminControllerIT.java index 482ccdbbb3b..9966f16bc41 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserAdminControllerIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserAdminControllerIT.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.List; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; import org.activiti.api.runtime.shared.security.SecurityContextPrincipalProvider; import org.activiti.api.task.runtime.TaskAdminRuntime; @@ -36,6 +37,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -95,9 +97,15 @@ class CandidateUserAdminControllerIT { @MockBean private RuntimeService runtimeService; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(pageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserControllerImplIT.java index fb7d3fa638f..65c83d42700 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/CandidateUserControllerImplIT.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.List; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; import org.activiti.api.runtime.shared.security.SecurityContextPrincipalProvider; @@ -38,6 +39,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -101,6 +103,12 @@ class CandidateUserControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(springPageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ConnectorDefinitionControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ConnectorDefinitionControllerImplIT.java index e8aaa2bedf0..197891cadb1 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ConnectorDefinitionControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ConnectorDefinitionControllerImplIT.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; import org.activiti.api.runtime.shared.security.SecurityContextPrincipalProvider; import org.activiti.cloud.services.events.ProcessEngineChannels; @@ -37,6 +38,7 @@ import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; import org.activiti.core.common.model.connector.ConnectorDefinition; import org.activiti.core.common.spring.connector.autoconfigure.ConnectorAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.runtime.api.conf.ConnectorsAutoConfiguration; @@ -92,6 +94,12 @@ class ConnectorDefinitionControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + + @MockBean + private ManagementService managementService; + @BeforeEach void setup() { assertThat(processExtensionService).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionAdminControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionAdminControllerImplIT.java index 00ae3de6043..710fbd02ebd 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionAdminControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionAdminControllerImplIT.java @@ -45,6 +45,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; @@ -121,6 +122,9 @@ class ProcessDefinitionAdminControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(processEngineChannels).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImplIT.java index 70be3aae50d..27dd35952f1 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessDefinitionControllerImplIT.java @@ -59,15 +59,18 @@ import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; import org.activiti.engine.ActivitiObjectNotFoundException; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.image.exception.ActivitiInterchangeInfoNotFoundException; import org.activiti.runtime.api.query.impl.PageImpl; import org.activiti.spring.process.CachingProcessExtensionService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; +import org.activiti.spring.process.model.ConstantDefinition; import org.activiti.spring.process.model.Extension; import org.activiti.spring.process.model.Mapping; import org.activiti.spring.process.model.Mapping.SourceMappingType; +import org.activiti.spring.process.model.ProcessConstantsMapping; import org.activiti.spring.process.model.ProcessVariablesMapping; import org.activiti.spring.process.model.VariableDefinition; import org.junit.jupiter.api.Test; @@ -144,6 +147,9 @@ class ProcessDefinitionControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + private final ObjectMapper om = new ObjectMapper(); @Test @@ -647,4 +653,320 @@ void should_getEmptyMapForProcessModelStaticValuesMappingForStartEvent_when_hasN assertThat(resultMap).isEqualTo(Map.of()); } + + @Test + void should_getProcessModelConstantsForStartEvent_when_hasStartEventFormAndConstants() throws Exception { + String procId = "procId"; + String my_process = "my process"; + String this_is_my_process = "this is my process"; + int version = 1; + ProcessDefinition processDefinition = buildProcessDefinition(procId, my_process, this_is_my_process, version); + List processDefinitionList = new ArrayList<>(); + processDefinitionList.add(processDefinition); + Page processDefinitionPage = new PageImpl<>( + processDefinitionList, + processDefinitionList.size() + ); + when(processRuntime.processDefinitions(any())).thenReturn(processDefinitionPage); + + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + process.setId(procId); + process.setName("Main Process"); + StartEvent startEvent = new StartEvent(); + startEvent.setName("startEvent"); + startEvent.setId("startEvent"); + startEvent.setFormKey("start-event-form"); + process.setInitialFlowElement(startEvent); + process.addFlowElement(startEvent); + bpmnModel.getProcesses().add(process); + when(repositoryService.getBpmnModel(procId)).thenReturn(bpmnModel); + + ProcessVariablesMapping startEventMapping = new ProcessVariablesMapping(); + Mapping valueMapping = new Mapping(); + valueMapping.setValue("static value"); + valueMapping.setType(SourceMappingType.VALUE); + Mapping variableMapping = new Mapping(); + variableMapping.setValue("variableRef"); + variableMapping.setType(SourceMappingType.VARIABLE); + startEventMapping.setInputs(Map.of("value", valueMapping, "variable", variableMapping)); + + ProcessConstantsMapping givenConstantsDefinition = new ProcessConstantsMapping(); + ConstantDefinition constantDefinition1 = new ConstantDefinition(); + constantDefinition1.setValue("Variable no 1"); + givenConstantsDefinition.put("variableRef", constantDefinition1); + + Extension extension = new Extension(); + extension.setConstants(Map.of("startEvent", givenConstantsDefinition)); + + when(cachingProcessExtensionService.getExtensionsForId("procId")).thenReturn(extension); + + MvcResult result = mockMvc + .perform(get("/v1/process-definitions/{id}/constant-values", procId).accept(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + Map resultMap = om.readValue(result.getResponse().getContentAsString(), Map.class); + + assertThat(resultMap).isEqualTo(Map.of("variableRef", "Variable no 1")); + } + + @Test + void should_getProcessModelConstantsForStartEvent_when_hasNoStartEventFormAndConstants() throws Exception { + String procId = "procId"; + String my_process = "my process"; + String this_is_my_process = "this is my process"; + int version = 1; + ProcessDefinition processDefinition = buildProcessDefinition(procId, my_process, this_is_my_process, version); + List processDefinitionList = new ArrayList<>(); + processDefinitionList.add(processDefinition); + Page processDefinitionPage = new PageImpl<>( + processDefinitionList, + processDefinitionList.size() + ); + when(processRuntime.processDefinitions(any())).thenReturn(processDefinitionPage); + + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + process.setId(procId); + process.setName("Main Process"); + StartEvent startEvent = new StartEvent(); + startEvent.setName("startEvent"); + startEvent.setId("startEvent"); + process.setInitialFlowElement(startEvent); + process.addFlowElement(startEvent); + bpmnModel.getProcesses().add(process); + when(repositoryService.getBpmnModel(procId)).thenReturn(bpmnModel); + + ProcessVariablesMapping startEventMapping = new ProcessVariablesMapping(); + Mapping valueMapping = new Mapping(); + valueMapping.setValue("static value"); + valueMapping.setType(SourceMappingType.VALUE); + Mapping variableMapping = new Mapping(); + variableMapping.setValue("variableRef"); + variableMapping.setType(SourceMappingType.VARIABLE); + startEventMapping.setInputs(Map.of("value", valueMapping, "variable", variableMapping)); + + ProcessConstantsMapping givenConstantsDefinition = new ProcessConstantsMapping(); + ConstantDefinition constantDefinition1 = new ConstantDefinition(); + constantDefinition1.setValue("Variable no 1"); + givenConstantsDefinition.put("variableRef", constantDefinition1); + + Extension extension = new Extension(); + extension.setConstants(Map.of("startEvent", givenConstantsDefinition)); + + when(cachingProcessExtensionService.getExtensionsForId("procId")).thenReturn(extension); + + MvcResult result = mockMvc + .perform(get("/v1/process-definitions/{id}/constant-values", procId).accept(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + Map resultMap = om.readValue(result.getResponse().getContentAsString(), Map.class); + + assertThat(resultMap).isEqualTo(Map.of("variableRef", "Variable no 1")); + } + + @Test + void should_getEmptyMapForProcessModelConstantsForStartEvent_when_startEventHasNoFormAndNoConstants() + throws Exception { + String procId = "procId"; + String my_process = "my process"; + String this_is_my_process = "this is my process"; + int version = 1; + ProcessDefinition processDefinition = buildProcessDefinition(procId, my_process, this_is_my_process, version); + List processDefinitionList = new ArrayList<>(); + processDefinitionList.add(processDefinition); + Page processDefinitionPage = new PageImpl<>( + processDefinitionList, + processDefinitionList.size() + ); + when(processRuntime.processDefinitions(any())).thenReturn(processDefinitionPage); + + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + process.setId(procId); + process.setName("Main Process"); + StartEvent startEvent = new StartEvent(); + startEvent.setName("startEvent"); + startEvent.setId("startEvent"); + process.setInitialFlowElement(startEvent); + process.addFlowElement(startEvent); + bpmnModel.getProcesses().add(process); + when(repositoryService.getBpmnModel(procId)).thenReturn(bpmnModel); + + ProcessVariablesMapping startEventMapping = new ProcessVariablesMapping(); + Mapping valueMapping = new Mapping(); + valueMapping.setValue("static value"); + valueMapping.setType(SourceMappingType.VALUE); + Mapping variableMapping = new Mapping(); + variableMapping.setValue("variableRef"); + variableMapping.setType(SourceMappingType.VARIABLE); + startEventMapping.setInputs(Map.of("value", valueMapping, "variable", variableMapping)); + + Extension extension = new Extension(); + + when(cachingProcessExtensionService.getExtensionsForId("procId")).thenReturn(extension); + + MvcResult result = mockMvc + .perform(get("/v1/process-definitions/{id}/constant-values", procId).accept(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + Map resultMap = om.readValue(result.getResponse().getContentAsString(), Map.class); + + assertThat(resultMap).isEqualTo(Map.of()); + } + + @Test + void should_getEmptyMapForProcessModelConstantsMappingForStartEvent_when_hasFormAndNoConstantsForStartEvent() + throws Exception { + String procId = "procId"; + String my_process = "my process"; + String this_is_my_process = "this is my process"; + int version = 1; + ProcessDefinition processDefinition = buildProcessDefinition(procId, my_process, this_is_my_process, version); + List processDefinitionList = new ArrayList<>(); + processDefinitionList.add(processDefinition); + Page processDefinitionPage = new PageImpl<>( + processDefinitionList, + processDefinitionList.size() + ); + when(processRuntime.processDefinitions(any())).thenReturn(processDefinitionPage); + + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + process.setId(procId); + process.setName("Main Process"); + StartEvent startEvent = new StartEvent(); + startEvent.setName("startEvent"); + startEvent.setId("startEvent"); + startEvent.setFormKey("start-event-form"); + process.setInitialFlowElement(startEvent); + process.addFlowElement(startEvent); + bpmnModel.getProcesses().add(process); + when(repositoryService.getBpmnModel(procId)).thenReturn(bpmnModel); + + ProcessVariablesMapping startEventMapping = new ProcessVariablesMapping(); + Mapping valueMapping = new Mapping(); + valueMapping.setValue("static value"); + valueMapping.setType(SourceMappingType.VALUE); + Mapping variableMapping = new Mapping(); + variableMapping.setValue("variableRef"); + variableMapping.setType(SourceMappingType.VARIABLE); + startEventMapping.setInputs(Map.of("value", valueMapping, "variable", variableMapping)); + + Extension extension = new Extension(); + + when(cachingProcessExtensionService.getExtensionsForId("procId")).thenReturn(extension); + + MvcResult result = mockMvc + .perform(get("/v1/process-definitions/{id}/constant-values", procId).accept(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + Map resultMap = om.readValue(result.getResponse().getContentAsString(), Map.class); + + assertThat(resultMap).isEqualTo(Map.of()); + } + + @Test + void should_getEmptyMapForProcessModelConstantsMappingForStartEvent_when_hasNoStartEvent() throws Exception { + String procId = "procId"; + String my_process = "my process"; + String this_is_my_process = "this is my process"; + int version = 1; + ProcessDefinition processDefinition = buildProcessDefinition(procId, my_process, this_is_my_process, version); + List processDefinitionList = new ArrayList<>(); + processDefinitionList.add(processDefinition); + Page processDefinitionPage = new PageImpl<>( + processDefinitionList, + processDefinitionList.size() + ); + when(processRuntime.processDefinitions(any())).thenReturn(processDefinitionPage); + + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + process.setId(procId); + process.setName("Main Process"); + bpmnModel.getProcesses().add(process); + when(repositoryService.getBpmnModel(procId)).thenReturn(bpmnModel); + + ProcessVariablesMapping startEventMapping = new ProcessVariablesMapping(); + Mapping valueMapping = new Mapping(); + valueMapping.setValue("static value"); + valueMapping.setType(SourceMappingType.VALUE); + Mapping variableMapping = new Mapping(); + variableMapping.setValue("variableRef"); + variableMapping.setType(SourceMappingType.VARIABLE); + startEventMapping.setInputs(Map.of("value", valueMapping, "variable", variableMapping)); + + ProcessConstantsMapping givenConstantsDefinition = new ProcessConstantsMapping(); + ConstantDefinition constantDefinition1 = new ConstantDefinition(); + constantDefinition1.setValue("Variable no 1"); + givenConstantsDefinition.put("variableRef", constantDefinition1); + + Extension extension = new Extension(); + extension.setConstants(Map.of("startEvent", givenConstantsDefinition)); + + when(cachingProcessExtensionService.getExtensionsForId("procId")).thenReturn(extension); + + MvcResult result = mockMvc + .perform(get("/v1/process-definitions/{id}/constant-values", procId).accept(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + Map resultMap = om.readValue(result.getResponse().getContentAsString(), Map.class); + + assertThat(resultMap).isEqualTo(Map.of()); + } + + @Test + void should_getEmptyMapForProcessModelConstantsMappingForStartEvent_when_hasNoExtensions() throws Exception { + String procId = "procId"; + String my_process = "my process"; + String this_is_my_process = "this is my process"; + int version = 1; + ProcessDefinition processDefinition = buildProcessDefinition(procId, my_process, this_is_my_process, version); + List processDefinitionList = new ArrayList<>(); + processDefinitionList.add(processDefinition); + Page processDefinitionPage = new PageImpl<>( + processDefinitionList, + processDefinitionList.size() + ); + when(processRuntime.processDefinitions(any())).thenReturn(processDefinitionPage); + + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + process.setId(procId); + process.setName("Main Process"); + StartEvent startEvent = new StartEvent(); + startEvent.setName("startEvent"); + startEvent.setId("startEvent"); + startEvent.setFormKey("start-event-form"); + process.setInitialFlowElement(startEvent); + process.addFlowElement(startEvent); + bpmnModel.getProcesses().add(process); + when(repositoryService.getBpmnModel(procId)).thenReturn(bpmnModel); + + ProcessVariablesMapping startEventMapping = new ProcessVariablesMapping(); + Mapping valueMapping = new Mapping(); + valueMapping.setValue("static value"); + valueMapping.setType(SourceMappingType.VALUE); + Mapping variableMapping = new Mapping(); + variableMapping.setValue("variableRef"); + variableMapping.setType(SourceMappingType.VARIABLE); + startEventMapping.setInputs(Map.of("value", valueMapping, "variable", variableMapping)); + + when(cachingProcessExtensionService.getExtensionsForId("procId")).thenReturn(null); + + MvcResult result = mockMvc + .perform(get("/v1/process-definitions/{id}/constant-values", procId).accept(APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + Map resultMap = om.readValue(result.getResponse().getContentAsString(), Map.class); + + assertThat(resultMap).isEqualTo(Map.of()); + } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImplIT.java index eabfe7c2b3c..a88876160fe 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceAdminControllerImplIT.java @@ -19,6 +19,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -53,6 +55,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.runtime.api.query.impl.PageImpl; @@ -131,6 +134,9 @@ class ProcessInstanceAdminControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(processEngineChannels).isNotNull(); @@ -193,6 +199,35 @@ void deleteProcessInstance() throws Exception { void destroyProcessInstance() throws Exception { this.mockMvc.perform(delete("/admin/v1/process-instances/{processInstanceId}/destroy", 1)) .andExpect(status().isOk()); + + verify(cloudProcessDeletedService, never()).delete(any()); + verify(cloudProcessDeletedService).sendDeleteEvent("1"); + } + + @Test + void destroyCancelledProcessInstance() throws Exception { + ProcessInstance processInstance = mock(ProcessInstance.class); + when(processInstance.getStatus()).thenReturn(ProcessInstanceStatus.CANCELLED); + when(processAdminRuntime.processInstance("1")).thenReturn(processInstance); + + this.mockMvc.perform(delete("/admin/v1/process-instances/{processInstanceId}/destroy", 1)) + .andExpect(status().isOk()); + + verify(cloudProcessDeletedService, never()).delete(any()); + verify(cloudProcessDeletedService).sendDeleteEvent("1"); + } + + @Test + void destroyRunningProcessInstanceWithForce() throws Exception { + ProcessInstance processInstance = mock(ProcessInstance.class); + when(processInstance.getStatus()).thenReturn(ProcessInstanceStatus.RUNNING); + when(processAdminRuntime.processInstance("1")).thenReturn(processInstance); + + this.mockMvc.perform(delete("/admin/v1/process-instances/{processInstanceId}/destroy?force=true", 1)) + .andExpect(status().isOk()); + + verify(cloudProcessDeletedService).delete("1"); + verify(cloudProcessDeletedService, never()).sendDeleteEvent("1"); } @Test @@ -204,6 +239,9 @@ void destroyProcessInstance_ShouldReturnBadRequestAsProcessIsNotCompletedOrCance this.mockMvc.perform(delete("/admin/v1/process-instances/{processInstanceId}/destroy", 1)) .andExpect(status().isBadRequest()); + + verify(cloudProcessDeletedService, never()).delete(any()); + verify(cloudProcessDeletedService, never()).sendDeleteEvent(any()); } @Test diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceControllerImplIT.java index 1f1534dd775..7ab2a18023e 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceControllerImplIT.java @@ -71,6 +71,7 @@ import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; import org.activiti.core.common.spring.security.policies.ActivitiForbiddenException; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.image.exception.ActivitiInterchangeInfoNotFoundException; @@ -144,6 +145,9 @@ class ProcessInstanceControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @Test void getProcessInstances() throws Exception { //given diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceTasksControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceTasksControllerImplIT.java index c9f845de701..f0a722a4090 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceTasksControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceTasksControllerImplIT.java @@ -41,6 +41,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.runtime.api.query.impl.PageImpl; @@ -112,6 +113,9 @@ class ProcessInstanceTasksControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(pageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableAdminControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableAdminControllerImplIT.java index d1fd531ac7d..ab4f3955684 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableAdminControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableAdminControllerImplIT.java @@ -47,6 +47,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -128,6 +129,9 @@ class ProcessInstanceVariableAdminControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { ProcessInstanceImpl processInstance; diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableControllerImplIT.java index 02475014937..172e5137c2c 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/ProcessInstanceVariableControllerImplIT.java @@ -46,6 +46,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.DateFormatterProvider; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.CachingProcessExtensionService; @@ -127,6 +128,9 @@ class ProcessInstanceVariableControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { //this assertion is not really necessary. It's only here to remove warning diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskAdminControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskAdminControllerImplIT.java index 7f8a115dbf1..d1559700a2c 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskAdminControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskAdminControllerImplIT.java @@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Collections; import java.util.List; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.shared.query.Page; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; import org.activiti.api.runtime.shared.security.SecurityContextPrincipalProvider; @@ -48,6 +49,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.runtime.api.query.impl.PageImpl; @@ -113,6 +115,12 @@ class TaskAdminControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(pageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskControllerImplIT.java index 6f690178075..098d7fc9732 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskControllerImplIT.java @@ -64,6 +64,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.runtime.api.query.impl.PageImpl; @@ -147,6 +148,9 @@ class TaskControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + @BeforeEach void setUp() { assertThat(springPageConverter).isNotNull(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableAdminControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableAdminControllerImplIT.java index 87d2d5c6b16..292e1fda287 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableAdminControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableAdminControllerImplIT.java @@ -46,6 +46,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -117,6 +118,9 @@ class TaskVariableAdminControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ManagementService managementService; + private static final String TASK_ID = UUID.randomUUID().toString(); private static final String PROCESS_INSTANCE_ID = UUID.randomUUID().toString(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableControllerImplIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableControllerImplIT.java index 503ff8935b2..79eafd78645 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableControllerImplIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-rest-impl/src/test/java/org/activiti/cloud/services/rest/controllers/TaskVariableControllerImplIT.java @@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Arrays; import java.util.UUID; +import org.activiti.api.process.runtime.ProcessAdminRuntime; import org.activiti.api.runtime.conf.impl.CommonModelAutoConfiguration; import org.activiti.api.runtime.model.impl.VariableInstanceImpl; import org.activiti.api.runtime.shared.security.PrincipalIdentityProvider; @@ -45,6 +46,7 @@ import org.activiti.cloud.services.rest.conf.ServicesRestWebMvcAutoConfiguration; import org.activiti.cloud.services.rest.config.StreamConfig; import org.activiti.common.util.conf.ActivitiCoreCommonUtilAutoConfiguration; +import org.activiti.engine.ManagementService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.spring.process.conf.ProcessExtensionsAutoConfiguration; @@ -112,6 +114,12 @@ class TaskVariableControllerImplIT { @MockBean private PrincipalIdentityProvider principalIdentityProvider; + @MockBean + private ProcessAdminRuntime processAdminRuntime; + + @MockBean + private ManagementService managementService; + private static final String TASK_ID = UUID.randomUUID().toString(); private static final String PROCESS_INSTANCE_ID = UUID.randomUUID().toString(); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-subscriptions/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-subscriptions/pom.xml index b9ed62f8fff..436c2b66fc6 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-subscriptions/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/activiti-cloud-services-subscriptions/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-subscriptions Activiti Cloud Services :: Subscriptions diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/messages-events/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/messages-events/pom.xml index 7392839f1c5..486261b9d23 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/messages-events/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/messages-events/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-services-runtime-bundle - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-services-messages-events diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/pom.xml index 53213aef889..2b8241e6fa1 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-services-runtime-bundle/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-runtime-bundle-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-runtime-bundle-dependencies activiti-cloud-services-runtime-bundle diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle-it/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle-it/pom.xml index b3a1ea08cb4..50fd6b60505 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle-it/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle-it/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-runtime-bundle-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-runtime-bundle-dependencies activiti-cloud-starter-runtime-bundle-it diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/pom.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/pom.xml index 9928a44e243..1361f717d48 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/pom.xml +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/pom.xml @@ -6,7 +6,7 @@ org.activiti.cloud activiti-cloud-runtime-bundle-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-runtime-bundle-dependencies activiti-cloud-starter-runtime-bundle diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessDefinitionRestTemplate.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessDefinitionRestTemplate.java index 7c22d107c78..11a42765de9 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessDefinitionRestTemplate.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessDefinitionRestTemplate.java @@ -67,4 +67,16 @@ public ResponseEntity> getProcessModelStaticValuesMappingFor assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); return responseEntity; } + + public ResponseEntity> getProcessModelConstantValuesForStartEvent(String id) { + ResponseEntity> responseEntity = testRestTemplate.exchange( + PROCESS_DEFINITIONS_URL.concat("/").concat(id).concat("/constant-values"), + HttpMethod.GET, + null, + new ParameterizedTypeReference<>() {} + ); + + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + return responseEntity; + } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessInstanceRestTemplate.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessInstanceRestTemplate.java index c34c99a64a6..1c2a6c41702 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessInstanceRestTemplate.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/helper/ProcessInstanceRestTemplate.java @@ -366,6 +366,24 @@ public ResponseEntity adminDelete( return responseEntity; } + public ResponseEntity adminDestroy( + ResponseEntity processInstanceEntity, + boolean force + ) { + assertThat(processInstanceEntity.getBody()).isNotNull(); + ResponseEntity responseEntity = testRestTemplate.exchange( + PROCESS_INSTANCES_ADMIN_RELATIVE_URL + .concat("/") + .concat(processInstanceEntity.getBody().getId()) + .concat("/destroy?force=" + force), + HttpMethod.DELETE, + null, + new ParameterizedTypeReference() {} + ); + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + return responseEntity; + } + public ResponseEntity suspend(ResponseEntity processInstanceEntity) { assertThat(processInstanceEntity.getBody()).isNotNull(); return suspend(PROCESS_INSTANCES_RELATIVE_URL, processInstanceEntity.getBody().getId()); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/AbstractMQServiceTaskIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/AbstractMQServiceTaskIT.java index 663dde7e431..86c7aa5eaae 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/AbstractMQServiceTaskIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/AbstractMQServiceTaskIT.java @@ -25,18 +25,26 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import org.activiti.api.model.shared.model.VariableInstance; import org.activiti.api.process.model.builders.ProcessPayloadBuilder; import org.activiti.api.task.model.builders.TaskPayloadBuilder; import org.activiti.cloud.api.model.shared.CloudVariableInstance; +import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; import org.activiti.cloud.api.process.model.CloudProcessInstance; import org.activiti.cloud.api.process.model.IntegrationRequest; +import org.activiti.cloud.api.process.model.events.CloudIntegrationResultReceivedEvent; +import org.activiti.cloud.api.process.model.events.CloudProcessCompletedEvent; import org.activiti.cloud.api.task.model.CloudTask; import org.activiti.cloud.services.test.containers.KeycloakContainerApplicationInitializer; import org.activiti.cloud.services.test.containers.RabbitMQContainerApplicationInitializer; import org.activiti.cloud.services.test.identity.IdentityTokenProducer; import org.activiti.cloud.starter.tests.helper.ProcessInstanceRestTemplate; import org.activiti.cloud.starter.tests.helper.TaskRestTemplate; +import org.activiti.cloud.starter.tests.services.audit.AuditConsumerStreamHandler; +import org.activiti.cloud.starter.tests.services.audit.AuditProducerIT; +import org.activiti.cloud.starter.tests.services.audit.ServicesAuditITConfiguration; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.runtime.ProcessInstance; @@ -44,6 +52,8 @@ import org.activiti.services.connectors.conf.ConnectorImplementationsProvider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.stream.config.BindingServiceProperties; @@ -51,17 +61,21 @@ import org.springframework.hateoas.PagedModel; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; +@ActiveProfiles(AuditProducerIT.AUDIT_PRODUCER_IT) @TestPropertySource("classpath:application-test.properties") @DirtiesContext @ContextConfiguration( - classes = RuntimeITConfiguration.class, + classes = { RuntimeITConfiguration.class, ServicesAuditITConfiguration.class }, initializers = { RabbitMQContainerApplicationInitializer.class, KeycloakContainerApplicationInitializer.class } ) public abstract class AbstractMQServiceTaskIT { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMQServiceTaskIT.class); + @Autowired protected RuntimeService runtimeService; @@ -83,6 +97,12 @@ public abstract class AbstractMQServiceTaskIT { @Autowired protected BindingServiceProperties bindingServiceProperties; + @Autowired + private AuditConsumerStreamHandler auditConsumer; + + @Autowired + private ServiceTaskConsumerHandler serviceTaskConsumerHandler; + @Value("${activiti.identity.test-user:hruser}") protected String keycloakTestUser; @@ -440,4 +460,72 @@ public void multiInstance_should_collectAllVariables_when_noDataItem() { ); }); } + + @Test + void should_beAbleToExecuteMultiInstanceServiceTasksAndNotMultiInstantiatedServiceTasksWithoutRaceConditions() + throws Exception { + //given + CompletableFuture singleInstanceCompletableFuture = CompletableFuture.supplyAsync(() -> + runtimeService.startProcessInstanceByKey( + "serviceTaskSingleInstanceRaceConditionWithOtherProcessWithMultiInstance" + ) + ); + + CompletableFuture multiInstanceCompletableFuture = CompletableFuture.supplyAsync(() -> { + waitForSingleInstanceToStart(); + ProcessInstance processWithMultiInstance = runtimeService.startProcessInstanceByKey( + "miSequentialServiceTaskRaceCondition" + ); + waitForFirstMultiInstanceToComplete(processWithMultiInstance); + + //when + resumeExecutionOfSingleInstance(); + return processWithMultiInstance; + }); + + //then + ProcessInstance singleProcessInstance = singleInstanceCompletableFuture.get(10, TimeUnit.SECONDS); + ProcessInstance multiInstanceProcess = multiInstanceCompletableFuture.get(10, TimeUnit.SECONDS); + await() + .untilAsserted(() -> + assertThat(auditConsumer.getAllReceivedEvents(CloudProcessCompletedEvent.class)) + .extracting(CloudRuntimeEvent::getProcessInstanceId, CloudRuntimeEvent::getProcessDefinitionKey) + .contains( + tuple(singleProcessInstance.getId(), singleProcessInstance.getProcessDefinitionKey()), + tuple(multiInstanceProcess.getId(), multiInstanceProcess.getProcessDefinitionKey()) + ) + ); + } + + private void resumeExecutionOfSingleInstance() { + serviceTaskConsumerHandler.getMultiInstanceLatch().countDown(); + LOGGER.info("Multi-instance latch counted down . Thread: {}", Thread.currentThread().threadId()); + } + + private void waitForFirstMultiInstanceToComplete(ProcessInstance processWithMultiInstance) { + LOGGER.info( + "Waiting for the first integration result for multi instance before counting down multi-instance latch... Thread: {}", + Thread.currentThread().threadId() + ); + await() + .untilAsserted(() -> + assertThat(auditConsumer.getAllReceivedEvents(CloudIntegrationResultReceivedEvent.class)) + .extracting(CloudIntegrationResultReceivedEvent::getProcessInstanceId) + .contains(processWithMultiInstance.getId()) + ); + } + + private void waitForSingleInstanceToStart() { + try { + LOGGER.info( + "Waiting for single instance latch to be counted down... Thread: {}", + Thread.currentThread().threadId() + ); + boolean conditionReached = serviceTaskConsumerHandler.getSingleInstanceLatch().await(5, TimeUnit.SECONDS); + assertThat(conditionReached).isTrue(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ConnectorIntegrationChannels.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ConnectorIntegrationChannels.java index f0e14470463..c82c885858a 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ConnectorIntegrationChannels.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ConnectorIntegrationChannels.java @@ -26,6 +26,8 @@ public interface ConnectorIntegrationChannels { String CONSTANTS_INTEGRATION_EVENTS_CONSUMER = "constantsIntegrationEventsConsumer"; String MEALS_CONNECTOR_CONSUMER = "mealsConnectorConsumer"; String VALUE_PROCESSOR_CONSUMER = "valueProcessorConsumer"; + String RACE_CONDITIONS_MULTI_INSTANCE_CONSUMER = "raceConditionsMultiInstanceConsumer"; + String RACE_CONDITION_SINGLE_INSTANCE_CONSUMER = "raceConditionsSingleInstanceConsumer"; @InputBinding(INTEGRATION_EVENTS_CONSUMER) default SubscribableChannel integrationEventsConsumer() { @@ -56,4 +58,14 @@ default SubscribableChannel mealsConnectorConsumer() { default SubscribableChannel valueProcessorConsumer() { return MessageChannels.publishSubscribe(VALUE_PROCESSOR_CONSUMER).getObject(); } + + @InputBinding(RACE_CONDITIONS_MULTI_INSTANCE_CONSUMER) + default SubscribableChannel raceConditionsMultiInstanceConsumer() { + return MessageChannels.publishSubscribe(RACE_CONDITIONS_MULTI_INSTANCE_CONSUMER).getObject(); + } + + @InputBinding(RACE_CONDITION_SINGLE_INSTANCE_CONSUMER) + default SubscribableChannel raceConditionsSingleInstanceConsumer() { + return MessageChannels.publishSubscribe(RACE_CONDITION_SINGLE_INSTANCE_CONSUMER).getObject(); + } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/MQServiceTaskIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/MQServiceTaskIT.java index 13737fdd7d8..7e61c28401c 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/MQServiceTaskIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/MQServiceTaskIT.java @@ -26,6 +26,7 @@ import java.util.Map; import org.activiti.api.process.model.IntegrationContext; import org.activiti.cloud.services.rest.api.ReplayServiceTaskRequest; +import org.activiti.cloud.starter.tests.services.audit.AuditProducerIT; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.junit.jupiter.api.Test; @@ -39,7 +40,9 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +@ActiveProfiles(AuditProducerIT.AUDIT_PRODUCER_IT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @DirtiesContext public class MQServiceTaskIT extends AbstractMQServiceTaskIT { diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessDefinitionIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessDefinitionIT.java index 94cc78bbecc..3b2f7cdd711 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessDefinitionIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessDefinitionIT.java @@ -102,4 +102,41 @@ public void shouldReturnEmptyMapWhenGettingStartEventStaticMappingsAndHasNoExten assertThat(staticValues.getBody()).isEqualTo(Map.of()); } + + @Test + public void shouldReturnStartEventConstantsOnlyWhenProcessHasStartEventFormAndMappings() { + ResponseEntity> staticValues = processDefinitionRestTemplate.getProcessModelConstantValuesForStartEvent( + processDefinitionIds.get("StartEventStaticMapping") + ); + + assertThat(staticValues.getBody()) + .isEqualTo(Map.of("startEnabled", "true", "startLabel", "Start the process", "cancelEnabled", "false")); + } + + @Test + public void shouldReturnEmptyMapWhenGettingStartEventConstantsAndHasNoStartEventForm() { + ResponseEntity> staticValues = processDefinitionRestTemplate.getProcessModelConstantValuesForStartEvent( + processDefinitionIds.get("shouldDeliverMessagesViaRestApi") + ); + + assertThat(staticValues.getBody()).isEqualTo(Map.of()); + } + + @Test + public void shouldReturnEmptyMapWhenGettingStartEventConstantsAndHasNoConstantsForStartEvent() { + ResponseEntity> staticValues = processDefinitionRestTemplate.getProcessModelConstantValuesForStartEvent( + processDefinitionIds.get("SimpleProcess") + ); + + assertThat(staticValues.getBody()).isEqualTo(Map.of()); + } + + @Test + public void shouldReturnEmptyMapWhenGettingStartEventConstantsAndHasNoExtensions() { + ResponseEntity> staticValues = processDefinitionRestTemplate.getProcessModelConstantValuesForStartEvent( + processDefinitionIds.get("ProcessWithVariables") + ); + + assertThat(staticValues.getBody()).isEqualTo(Map.of()); + } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessInstanceIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessInstanceIT.java index 1da29643c27..7b14f10540a 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessInstanceIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ProcessInstanceIT.java @@ -15,8 +15,10 @@ */ package org.activiti.cloud.starter.tests.runtime; +import static org.activiti.api.process.model.events.ProcessRuntimeEvent.ProcessEvents.PROCESS_DELETED; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.verify; import java.io.ByteArrayInputStream; @@ -34,6 +36,7 @@ import org.activiti.bpmn.converter.BpmnXMLConverter; import org.activiti.bpmn.converter.util.InputStreamProvider; import org.activiti.bpmn.model.BpmnModel; +import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; import org.activiti.cloud.api.process.model.CloudProcessDefinition; import org.activiti.cloud.api.process.model.CloudProcessInstance; import org.activiti.cloud.api.process.model.events.CloudProcessStartedEvent; @@ -110,6 +113,9 @@ class ProcessInstanceIT { @Captor private ArgumentCaptor processStartedEventArgumentCaptor; + @Captor + private ArgumentCaptor> cloudRuntimeEventArgumentCaptor; + @BeforeEach void setUp() { keycloakTestUser = "hruser"; @@ -666,6 +672,41 @@ void adminShouldDeleteProcessInstance() { .isThrownBy(() -> processInstanceRestTemplate.getProcessInstance(processEntity)); } + @Test + void adminShouldForceDestroyProcessInstance() { + //given + ResponseEntity processEntity = processInstanceRestTemplate.startProcess( + processDefinitionIds.get(SIMPLE_PROCESS), + null, + "business_key" + ); + + assertThat(processEntity).isNotNull(); + assertThat(processEntity.getBody()).isNotNull(); + assertThat(processEntity.getBody().getId()).isNotNull(); + assertThat(processEntity.getBody().getProcessDefinitionId()).contains("SimpleProcess:"); + + //when + identityTokenProducer.withTestUser("testadmin"); + ResponseEntity responseEntity = processInstanceRestTemplate.adminDestroy( + processEntity, + true + ); + + //then + assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> processInstanceRestTemplate.getProcessInstance(processEntity)) + .withMessageContaining("404 NOT_FOUND"); + + verify(this.processEngineEventsAggregator, atLeast(1)).add(this.cloudRuntimeEventArgumentCaptor.capture()); + assertThat(cloudRuntimeEventArgumentCaptor.getAllValues()) + .isNotEmpty() + .extracting("eventType") + .contains(PROCESS_DELETED); + } + private void assertEventActorIsSet(String processInstanceId) { List identityLinksForProcessInstance = this.runtimeService.getIdentityLinksForProcessInstance(processInstanceId); diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ServiceTaskConsumerHandler.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ServiceTaskConsumerHandler.java index 49681c0dbca..7dd525d6053 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ServiceTaskConsumerHandler.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/runtime/ServiceTaskConsumerHandler.java @@ -25,6 +25,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import org.activiti.api.process.model.IntegrationContext; @@ -32,6 +34,8 @@ import org.activiti.cloud.common.messaging.functional.ConditionalFunctionBinding; import org.activiti.cloud.common.messaging.functional.FunctionBinding; import org.assertj.core.api.Assertions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; @@ -69,6 +73,20 @@ public class ServiceTaskConsumerHandler { private List meals = Arrays.asList("pizza", "pasta"); private List sizes = Arrays.asList("small", "medium"); + private CountDownLatch multiInstanceLatch = new CountDownLatch(1); + + private CountDownLatch singleInstanceLatch = new CountDownLatch(1); + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTaskConsumerHandler.class); + + public CountDownLatch getSingleInstanceLatch() { + return singleInstanceLatch; + } + + public CountDownLatch getMultiInstanceLatch() { + return multiInstanceLatch; + } + @FunctionBinding(input = ConnectorIntegrationChannels.INTEGRATION_EVENTS_CONSUMER) @Bean public Consumer> receiveRequestConnector() { @@ -256,4 +274,45 @@ public Consumer> valueProcessorConnector() { integrationResultSender.send(message.getPayload(), integrationContext); }; } + + @FunctionBinding(input = ConnectorIntegrationChannels.RACE_CONDITIONS_MULTI_INSTANCE_CONSUMER) + @Bean + public Consumer> raceConditionMultiInstanceConnector() { + return message -> { + integrationResultSender.send(message.getPayload(), message.getPayload().getIntegrationContext()); + LOGGER.info("Integration result sent for multi-instance. Thread: {}", Thread.currentThread().threadId()); + }; + } + + @FunctionBinding(input = ConnectorIntegrationChannels.RACE_CONDITION_SINGLE_INSTANCE_CONSUMER) + @Bean + public Consumer> raceConditionSingleInstanceConnector() { + return message -> { + try { + // unblock who was waiting for single instance service task to start (integration result for single + // service task) + singleInstanceLatch.countDown(); + LOGGER.info( + "Single instance started: single instance latch counted down. Waiting for multi-instance latch to be counted down... Thread: {}", + Thread.currentThread().threadId() + ); + boolean conditionReached = multiInstanceLatch.await(5, TimeUnit.SECONDS); + if (conditionReached) { + LOGGER.info( + "Proceeding with the execution of single instance. Thread: {}", + Thread.currentThread().threadId() + ); + } else { + LOGGER.info( + "Timeout while waiting for multi-instance latch to be counted down. Thread: {}", + Thread.currentThread().threadId() + ); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + integrationResultSender.send(message.getPayload(), message.getPayload().getIntegrationContext()); + }; + } } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditConsumerStreamHandler.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditConsumerStreamHandler.java index 36aa9d2747a..4f570be1115 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditConsumerStreamHandler.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditConsumerStreamHandler.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.activiti.cloud.api.model.shared.events.CloudRuntimeEvent; import org.activiti.cloud.common.messaging.functional.FunctionBinding; import org.springframework.boot.test.context.TestConfiguration; @@ -60,6 +61,14 @@ public class AuditConsumerStreamHandler { return allReceivedEvents; } + public > List getAllReceivedEvents(Class eventType) { + return allReceivedEvents + .stream() + .filter(eventType::isInstance) + .map(eventType::cast) + .collect(Collectors.toList()); + } + public Map getReceivedHeaders() { return receivedHeaders; } diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditProducerIT.java b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditProducerIT.java index bbc62108ca9..efa422a21bd 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditProducerIT.java +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/java/org/activiti/cloud/starter/tests/services/audit/AuditProducerIT.java @@ -133,7 +133,7 @@ initializers = { KeycloakContainerApplicationInitializer.class } ) @Import(TestChannelBinderConfiguration.class) -class AuditProducerIT { +public class AuditProducerIT { private static final String SIMPLE_SUB_PROCESS1 = "simpleSubProcess1"; private static final String SIMPLE_SUB_PROCESS2 = "simpleSubProcess2"; diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/application-test.properties b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/application-test.properties index c23e9a31c61..5f8d605bf0f 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/application-test.properties +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/application-test.properties @@ -61,6 +61,14 @@ spring.cloud.stream.bindings.canFailConnector.destination=connector.canFail spring.cloud.stream.bindings.canFailConnector.group=integration spring.cloud.stream.bindings.canFailConnector.contentType=application/json +# Race condition test connectors +spring.cloud.stream.bindings.raceConditionsMultiInstanceConsumer.destination=testRaceConditionMultipleInstances +spring.cloud.stream.bindings.raceConditionsMultiInstanceConsumer.group=integration +spring.cloud.stream.bindings.raceConditionsMultiInstanceConsumer.contentType=application/json + +spring.cloud.stream.bindings.raceConditionsSingleInstanceConsumer.destination=testRaceConditionSingleInstance +spring.cloud.stream.bindings.raceConditionsSingleInstanceConsumer.group=integration +spring.cloud.stream.bindings.raceConditionsSingleInstanceConsumer.contentType=application/json activiti.identity.test-user=hruser activiti.identity.test-password=password diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/StartEventStaticMapping-extensions.json b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/StartEventStaticMapping-extensions.json index b61076eaf3d..cb065d96a0f 100644 --- a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/StartEventStaticMapping-extensions.json +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/StartEventStaticMapping-extensions.json @@ -3,7 +3,19 @@ "name": "myProcess.bpmn", "extensions": { "StartEventStaticMapping": { - "constants": {}, + "constants": { + "Event_1": { + "startEnabled": { + "value": "true" + }, + "startLabel": { + "value": "Start the process" + }, + "cancelEnabled": { + "value": "false" + } + } + }, "mappings": { "Task_03vo218": { "inputs": { diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/multi-instance-sequence-servicetask-racecondition.bpmn20.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/multi-instance-sequence-servicetask-racecondition.bpmn20.xml new file mode 100644 index 00000000000..741047983be --- /dev/null +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/multi-instance-sequence-servicetask-racecondition.bpmn20.xml @@ -0,0 +1,22 @@ + + + + + + + + + + ${2} + + + + + + + + diff --git a/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/service-task-single-racecondition-with-multi-instance.bpmn20.xml b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/service-task-single-racecondition-with-multi-instance.bpmn20.xml new file mode 100644 index 00000000000..3147822ddb4 --- /dev/null +++ b/activiti-cloud-runtime-bundle-service/activiti-cloud-starter-runtime-bundle/src/test/resources/processes/service-task-single-racecondition-with-multi-instance.bpmn20.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/activiti-cloud-runtime-bundle-service/pom.xml b/activiti-cloud-runtime-bundle-service/pom.xml index 3e77139a687..077b72367a3 100644 --- a/activiti-cloud-runtime-bundle-service/pom.xml +++ b/activiti-cloud-runtime-bundle-service/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-runtime-bundle-service-parent @@ -18,7 +18,7 @@ activiti-cloud-starter-runtime-bundle-it - 8.5.0-alpha.4 + 8.7.0-alpha.27 1.5 diff --git a/activiti-cloud-service-common/activiti-cloud-service-common-config/pom.xml b/activiti-cloud-service-common/activiti-cloud-service-common-config/pom.xml index 54677208475..e0dfd015f37 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-common-config/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-service-common-config/pom.xml @@ -4,7 +4,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies 4.0.0 diff --git a/activiti-cloud-service-common/activiti-cloud-service-common-dependencies/pom.xml b/activiti-cloud-service-common/activiti-cloud-service-common-dependencies/pom.xml index a3a4d1157c6..eaacc722219 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-common-dependencies/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-service-common-dependencies/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-service-common-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT activiti-cloud-service-common-dependencies pom diff --git a/activiti-cloud-service-common/activiti-cloud-service-common-liquibase/pom.xml b/activiti-cloud-service-common/activiti-cloud-service-common-liquibase/pom.xml index fab5805a29d..0d666de2560 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-common-liquibase/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-service-common-liquibase/pom.xml @@ -3,7 +3,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-service-common-liquibase diff --git a/activiti-cloud-service-common/activiti-cloud-service-error-handlers/pom.xml b/activiti-cloud-service-common/activiti-cloud-service-error-handlers/pom.xml index f018740e5db..4285e99e82a 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-error-handlers/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-service-error-handlers/pom.xml @@ -4,7 +4,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies 4.0.0 diff --git a/activiti-cloud-service-common/activiti-cloud-service-messaging-config/pom.xml b/activiti-cloud-service-common/activiti-cloud-service-messaging-config/pom.xml index 0a277c7d632..57ceb7052e6 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-messaging-config/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-service-messaging-config/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies 4.0.0 diff --git a/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/ActivitiMessagingDestinationTransformer.java b/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/ActivitiMessagingDestinationTransformer.java index b1d22694900..05623c6505c 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/ActivitiMessagingDestinationTransformer.java +++ b/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/ActivitiMessagingDestinationTransformer.java @@ -59,7 +59,7 @@ public String apply(String source) { .filter(StringUtils::hasText) .orElse(source); - log.warn( + log.debug( "Processing source destination '{}' with prefix '{}' and separator '{} to target name '{}' with scope '{}'", source, prefix, diff --git a/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/FunctionBindingConfiguration.java b/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/FunctionBindingConfiguration.java index 69d6b217806..47c64cd54b1 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/FunctionBindingConfiguration.java +++ b/activiti-cloud-service-common/activiti-cloud-service-messaging-config/src/main/java/org/activiti/cloud/common/messaging/config/FunctionBindingConfiguration.java @@ -17,13 +17,20 @@ import static org.springframework.integration.handler.LoggingHandler.Level.DEBUG; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.lang.reflect.Type; +import java.math.BigDecimal; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import org.activiti.cloud.common.messaging.functional.FunctionBinding; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionResolver; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -32,11 +39,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.cloud.function.context.FunctionRegistration; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; +import org.springframework.cloud.function.json.JacksonMapper; import org.springframework.cloud.stream.config.BinderFactoryAutoConfiguration; import org.springframework.cloud.stream.config.BindingServiceProperties; import org.springframework.cloud.stream.function.FunctionConfiguration; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Primary; import org.springframework.integration.core.GenericHandler; import org.springframework.integration.core.GenericSelector; import org.springframework.integration.dsl.IntegrationFlow; @@ -188,4 +198,28 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw } public interface BindingResolver extends Function {} + + @Bean + @ConditionalOnClass(JacksonMapper.class) + @Primary + public JacksonMapper jacksonMapper(@Autowired(required = false) ObjectMapper objectMapper) { + //temporary workaround for https://github.com/spring-cloud/spring-cloud-function/issues/1159 + ObjectMapper copiedMapper; + if (objectMapper == null) { + copiedMapper = new ObjectMapper(); + copiedMapper.registerModule(new JavaTimeModule()); + copiedMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + copiedMapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true); + copiedMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } else { + try { + copiedMapper = objectMapper.copy(); + } catch (Exception e) { + copiedMapper = new ObjectMapper(); + } + } + //logic from AlfrescoWebAutoConfiguration.configureObjectMapperForBigDecimal + copiedMapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + return new JacksonMapper(copiedMapper); + } } diff --git a/activiti-cloud-service-common/activiti-cloud-service-messaging-starter/pom.xml b/activiti-cloud-service-common/activiti-cloud-service-messaging-starter/pom.xml index 71843b4a24f..ad071010c10 100644 --- a/activiti-cloud-service-common/activiti-cloud-service-messaging-starter/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-service-messaging-starter/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies 4.0.0 diff --git a/activiti-cloud-service-common/activiti-cloud-services-auditable/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-auditable/pom.xml index fa04796ee99..fd12ab7eefb 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-auditable/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-auditable/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-auditable diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-identity-keycloak/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-common-identity-keycloak/pom.xml index 92c5d8a379f..3ff67756ed2 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-identity-keycloak/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-common-identity-keycloak/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-service-common-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-common-identity-keycloak diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/pom.xml index 67f64b1de9f..9a5e6d51d77 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-common-security-keycloak diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapter.java b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapter.java index edb5641f1f0..a91e8e6e63e 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapter.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapter.java @@ -59,4 +59,9 @@ public List getGroups() { private List getRoles(Map getRolesParent) { return (List) getRolesParent.get("roles"); } + + @Override + public List getScopes() { + return jwt.getClaimAsStringList("scope"); + } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakResourceJwtAdapter.java b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakResourceJwtAdapter.java index 753602f9cc4..44244907e72 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakResourceJwtAdapter.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/KeycloakResourceJwtAdapter.java @@ -46,6 +46,11 @@ public List getPermissions() { return getFromClient(resourceId, "permissions", jwt); } + @Override + public List getScopes() { + return jwt.getClaimAsStringList("scope"); + } + @Override public List getGroups() { if (jwt.hasClaim("groups")) { diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/config/KeycloakSecurityConfiguration.java b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/config/KeycloakSecurityConfiguration.java index 6d5a81476a9..e177717e1c5 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/config/KeycloakSecurityConfiguration.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/java/org/activiti/cloud/services/common/security/keycloak/config/KeycloakSecurityConfiguration.java @@ -64,10 +64,12 @@ public JwtAccessTokenProvider jwtAccessTokenProvider(Function j @ConditionalOnMissingBean public OAuthFlow swaggerOAuthFlow( @Value("${keycloak.auth-server-url}") String authServer, - @Value("${keycloak.realm}") String realm + @Value("${keycloak.realm}") String realm, + @Value("${spring.security.oauth2.client.provider.keycloak.token-uri}") String tokenUrl ) { return new OAuthFlow() .authorizationUrl(authServer + "/realms/" + realm + "/protocol/openid-connect/auth") + .tokenUrl(tokenUrl) .scopes(new Scopes()); } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/resources/keycloak-configuration.properties b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/resources/keycloak-configuration.properties index 2308d548365..fd572f85642 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/resources/keycloak-configuration.properties +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/main/resources/keycloak-configuration.properties @@ -23,3 +23,5 @@ spring.security.oauth2.client.registration.keycloak.scope=openid spring.security.oauth2.client.provider.keycloak.authorization-uri=${keycloak.auth-server-url}/realms/${keycloak.realm}/protocol/openid-connect/authorize spring.security.oauth2.client.provider.keycloak.token-uri=${keycloak.auth-server-url}/realms/${keycloak.realm}/protocol/openid-connect/token + +springdoc.swagger-ui.oauth.usePkceWithAuthorizationCodeGrant=true diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/test/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapterTest.java b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/test/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapterTest.java index a5b02d4fab2..b1b15b47117 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/test/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapterTest.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security-keycloak/src/test/java/org/activiti/cloud/services/common/security/keycloak/KeycloakJwtAdapterTest.java @@ -63,4 +63,12 @@ public void shouldReturnRoles() { assertThat(keycloakJwtAdapter.getRoles()).hasSize(2).containsExactly("roleA", "roleB"); } + + @Test + public void shouldReturnScope() { + Map rolesParent = JSONObjectUtils.newJSONObject(); + rolesParent.put("scope", List.of("scopeA", "scopeB")); + when(jwt.getClaimAsStringList("scope")).thenReturn(List.of("scopeA", "scopeB")); + assertThat(keycloakJwtAdapter.getScopes()).hasSize(2).containsExactly("scopeA", "scopeB"); + } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-common-security/pom.xml index c2386d117a4..da9175de3a1 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-common-security diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/security/authorization/CustomAuthorizationManager.java b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/security/authorization/CustomAuthorizationManager.java index 6f1bafa5842..b0baecbf5a7 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/security/authorization/CustomAuthorizationManager.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/security/authorization/CustomAuthorizationManager.java @@ -29,6 +29,7 @@ public class CustomAuthorizationManager public static final String ROLE_PREFIX = "ROLE_"; public static final String PERMISSION_PREFIX = "PERMISSION_"; + public static final String SCOPE_PREFIX = "SCOPE_"; private final Set authoritiesWithAccess; diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtAdapter.java b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtAdapter.java index 90c6830650d..351335640bf 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtAdapter.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtAdapter.java @@ -28,6 +28,8 @@ public interface JwtAdapter { List getGroups(); + List getScopes(); + default List getPermissions() { return Collections.emptyList(); } diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtGrantedAuthorityConverter.java b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtGrantedAuthorityConverter.java index 2d0c93416aa..4c00b41868a 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtGrantedAuthorityConverter.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtGrantedAuthorityConverter.java @@ -34,14 +34,18 @@ public JwtGrantedAuthorityConverter(JwtAccessTokenProvider jwtAccessTokenProvide @Override public Collection convert(Jwt jwt) { Collection grantedAuthorities = new ArrayList<>(); - for (String role : jwtAccessTokenProvider.accessToken(jwt).getRoles()) { + JwtAdapter jwtAdapter = jwtAccessTokenProvider.accessToken(jwt); + for (String role : jwtAdapter.getRoles()) { grantedAuthorities.add(new SimpleGrantedAuthority(CustomAuthorizationManager.ROLE_PREFIX + role)); } - for (String permission : jwtAccessTokenProvider.accessToken(jwt).getPermissions()) { + for (String permission : jwtAdapter.getPermissions()) { grantedAuthorities.add( new SimpleGrantedAuthority(CustomAuthorizationManager.PERMISSION_PREFIX + permission) ); } + for (String scope : jwtAdapter.getScopes()) { + grantedAuthorities.add(new SimpleGrantedAuthority(CustomAuthorizationManager.SCOPE_PREFIX + scope)); + } return grantedAuthorities; } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtUserInfoUriAuthenticationConverter.java b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtUserInfoUriAuthenticationConverter.java index c77fb4cd602..92609713798 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtUserInfoUriAuthenticationConverter.java +++ b/activiti-cloud-service-common/activiti-cloud-services-common-security/src/main/java/org/activiti/cloud/services/common/security/jwt/JwtUserInfoUriAuthenticationConverter.java @@ -72,8 +72,11 @@ public String getPrincipalClaimName(Jwt jwt) { expiresAt ); OAuth2UserRequest userRequest = new OAuth2UserRequest(clientRegistration, accessToken); - OAuth2User oAuth2User = this.oAuth2UserServiceCacheable.loadUser(userRequest, getCacheKey(jwt)); - username = oAuth2User.getName(); + String cacheKey = getCacheKey(jwt); + if (cacheKey != null) { + OAuth2User oAuth2User = this.oAuth2UserServiceCacheable.loadUser(userRequest, cacheKey); + username = oAuth2User.getName(); + } } return username; } diff --git a/activiti-cloud-service-common/activiti-cloud-services-common-util/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-common-util/pom.xml index 0ae52f7cc73..288901fe060 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-common-util/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-common-util/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-common-util diff --git a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/pom.xml index b2f193d13f3..b2e6d15f3ed 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-dbp-rest diff --git a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolver.java b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolver.java index ecd2e18af73..15ff3b1798a 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolver.java +++ b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolver.java @@ -29,12 +29,19 @@ public class AlfrescoPageArgumentMethodResolver implements PageableArgumentResol private final AlfrescoPageParameterParser pageParameterParser; private final PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver; + private final int maxItemsLimit; + private final boolean maxItemsLimitEnabled; + public AlfrescoPageArgumentMethodResolver( AlfrescoPageParameterParser pageParameterParser, - PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver + PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver, + int maxItemsLimit, + boolean maxItemsLimitEnabled ) { this.pageParameterParser = pageParameterParser; this.pageableHandlerMethodArgumentResolver = pageableHandlerMethodArgumentResolver; + this.maxItemsLimit = maxItemsLimit; + this.maxItemsLimitEnabled = maxItemsLimitEnabled; } @Override @@ -58,7 +65,10 @@ public Pageable resolveArgument( ); AlfrescoQueryParameters alfrescoQueryParameters = pageParameterParser.parseParameters(webRequest); - if ( + + if (isPaginationValueExceedingLimit(alfrescoQueryParameters, basePageable)) { + throw new IllegalStateException("Exceeded max limit of " + maxItemsLimit + " elements"); + } else if ( alfrescoQueryParameters.getSkipCountParameter().isSet() || alfrescoQueryParameters.getMaxItemsParameter().isSet() ) { @@ -71,4 +81,18 @@ public Pageable resolveArgument( return basePageable; } } + + private boolean isPaginationValueExceedingLimit( + AlfrescoQueryParameters alfrescoQueryParameters, + Pageable basePageable + ) { + if (maxItemsLimitEnabled) { + if (alfrescoQueryParameters.getMaxItemsParameter().isSet()) { + return alfrescoQueryParameters.getMaxItemsParameter().getValue() > maxItemsLimit; + } else { + return basePageable.getPageSize() > maxItemsLimit; + } + } + return false; + } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfiguration.java b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfiguration.java index 1d9cf1d7652..30fe19aa08b 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfiguration.java +++ b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfiguration.java @@ -50,13 +50,19 @@ public class AlfrescoWebAutoConfiguration implements WebMvcConfigurer { private final PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver; private final int defaultPageSize; + private final int maxItemsLimit; + private final boolean maxItemsLimitEnabled; public AlfrescoWebAutoConfiguration( @Lazy PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver, - @Value("${spring.data.rest.default-page-size:100}") int defaultPageSize + @Value("${spring.data.rest.default-page-size:100}") int defaultPageSize, + @Value("${activiti.cloud.rest.max-items}") int maxItemsLimit, + @Value("${activiti.cloud.rest.max-items.enabled}") boolean maxItemsLimitEnabled ) { this.pageableHandlerMethodArgumentResolver = pageableHandlerMethodArgumentResolver; this.defaultPageSize = defaultPageSize; + this.maxItemsLimit = maxItemsLimit; + this.maxItemsLimitEnabled = maxItemsLimitEnabled; } @Override @@ -65,7 +71,9 @@ public void addArgumentResolvers(List resolvers) 0, new AlfrescoPageArgumentMethodResolver( new AlfrescoPageParameterParser(defaultPageSize), - pageableHandlerMethodArgumentResolver + pageableHandlerMethodArgumentResolver, + maxItemsLimit, + maxItemsLimitEnabled ) ); } diff --git a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/resources/config/alfresco-rest-config.properties b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/resources/config/alfresco-rest-config.properties index bcb91970054..18083da80a3 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/resources/config/alfresco-rest-config.properties +++ b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/main/resources/config/alfresco-rest-config.properties @@ -1,3 +1,6 @@ spring.data.rest.default-page-size=100 spring.data.rest.default-media-type=application/json spring.hateoas.use-hal-as-default-json-media-type=false + +activiti.cloud.rest.max-items=${MAX_ITEMS_LIMIT:1000} +activiti.cloud.rest.max-items.enabled=${MAX_ITEMS_LIMIT_ENABLED:true} diff --git a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolverTest.java b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolverTest.java index 40c4aa933ec..2080225f58d 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolverTest.java +++ b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/argument/resolver/AlfrescoPageArgumentMethodResolverTest.java @@ -20,11 +20,10 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import java.util.Collections; import org.activiti.test.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.MethodParameter; @@ -37,7 +36,6 @@ @ExtendWith(MockitoExtension.class) public class AlfrescoPageArgumentMethodResolverTest { - @InjectMocks private AlfrescoPageArgumentMethodResolver alfrescoPageArgumentMethodResolver; @Mock @@ -46,6 +44,17 @@ public class AlfrescoPageArgumentMethodResolverTest { @Mock private PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver; + @BeforeEach + public void setUp() { + this.alfrescoPageArgumentMethodResolver = + new AlfrescoPageArgumentMethodResolver( + pageParameterParser, + pageableHandlerMethodArgumentResolver, + 1000, + true + ); + } + @Test public void supportsParameterShouldReturnTrueWhenItsAPageable() throws Exception { //given diff --git a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfigurationTest.java b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfigurationTest.java index 345686cb7e3..da5e5657223 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfigurationTest.java +++ b/activiti-cloud-service-common/activiti-cloud-services-dbp-rest/src/test/java/org/activiti/cloud/alfresco/config/AlfrescoWebAutoConfigurationTest.java @@ -45,7 +45,7 @@ public class AlfrescoWebAutoConfigurationTest { @BeforeEach public void setUp() { - configurer = new AlfrescoWebAutoConfiguration(pageableHandlerMethodArgumentResolver, 100); + configurer = new AlfrescoWebAutoConfiguration(pageableHandlerMethodArgumentResolver, 100, 1000, true); } @Test diff --git a/activiti-cloud-service-common/activiti-cloud-services-logging/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-logging/pom.xml index bf315b4b5db..5f80dd98ff4 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-logging/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-logging/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-logging diff --git a/activiti-cloud-service-common/activiti-cloud-services-metadata/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-metadata/pom.xml index 88d7cb21839..68d62c28df3 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-metadata/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-metadata/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-metadata diff --git a/activiti-cloud-service-common/activiti-cloud-services-monitoring/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-monitoring/pom.xml index 06e1f91fd5d..8d92ef29a38 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-monitoring/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-monitoring/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-monitoring diff --git a/activiti-cloud-service-common/activiti-cloud-services-swagger/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-swagger/pom.xml index c996ef608ff..014d313ee33 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-swagger/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-swagger/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-swagger diff --git a/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/java/org/activiti/cloud/common/swagger/springdoc/BaseOpenApiBuilder.java b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/java/org/activiti/cloud/common/swagger/springdoc/BaseOpenApiBuilder.java index ab81adc9975..e7339bb509e 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/java/org/activiti/cloud/common/swagger/springdoc/BaseOpenApiBuilder.java +++ b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/java/org/activiti/cloud/common/swagger/springdoc/BaseOpenApiBuilder.java @@ -77,6 +77,6 @@ private SecurityScheme securityScheme() { .bearerFormat("jwt") .in(SecurityScheme.In.HEADER) .description("Authorizing with SSO") - .flows(new OAuthFlows().implicit(swaggerOAuthFlow)); + .flows(new OAuthFlows().authorizationCode(swaggerOAuthFlow)); } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/resources/META-INF/resources/webjars/swagger-ui/custom-swagger.js b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/resources/META-INF/resources/webjars/swagger-ui/custom-swagger.js new file mode 100644 index 00000000000..54d445fd50e --- /dev/null +++ b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/resources/META-INF/resources/webjars/swagger-ui/custom-swagger.js @@ -0,0 +1,132 @@ +function buildFormData(data) { + let formArr = []; + + for (let name in data) { + let val = data[name]; + if (val !== undefined && val !== '') { + formArr.push( + [name, '=', encodeURIComponent(val).replace(/%20/g, '+')].join(''), + ); + } + } + return formArr.join('&'); +} + +function getAuth() { + return window.ui.authSelectors.authorized().toJS()?.oauth; +} + +function tryRefreshOauth2Token() { + const auth = getAuth(); + if (!auth) { + console.log(`Swagger is not authorized. Can't refresh token.`); + return; + } + + const {schema, clientId, token} = auth; + const errors = []; + + if (schema == null) { + errors.push('Invalid auth: missing schema'); + } + if (schema?.tokenUrl == null) { + errors.push('Invalid auth schema: missing tokenUrl'); + } + if (clientId == null) { + errors.push('Invalid auth: missing clientId'); + } + + if (token == null) { + errors.push('Invalid auth: missing token'); + } + if (token?.refresh_token == null) { + errors.push('Invalid auth: missing refresh token'); + } + if (token?.scope == null) { + errors.push('Invalid auth: missing scope'); + } + if (errors.length) { + console.log("Can't refresh token due to the following issues:"); + errors.forEach(console.log); + return; + } + + const form = { + grant_type: 'refresh_token', + refresh_token: token.refresh_token, + client_id: clientId, + scope: token.scope, + }; + + console.log(`Refreshing token...`); + window.ui.authActions.authorizeRequest({ + body: buildFormData(form), + name, + url: schema.tokenUrl, + auth, + }); +} + +function startClock() { + function tick() { + const remainingRefreshTime = window.tokenRefreshTime - Date.now(); + + if (remainingRefreshTime < 0) { + clearInterval(window.tokenClockInterval); + tryRefreshOauth2Token(); + } + } + + if (window.tokenClockInterval) clearInterval(window.tokenClockInterval); + + window.tokenClockInterval = setInterval(tick, 500); + tick(); +} + +let patchTries = 10; + +function patchRefreshHook() { + if (!window?.ui?.authActions?.authorizeOauth2) { + if (patchTries) { + patchTries--; + setTimeout(patchRefreshHook, 1000); + console.log( + 'Missing patch target function "window.ui.authActions.authorizeOauth2", retrying in 1s...', + ); + return; + } + console.log( + 'Cannot patch OAuth token refresh hook. Missing patch target function "window.ui.authActions.authorizeOauth2"', + ); + return; + } + + console.log('Patching OAuth token refresh hook...'); + const origAuthorizeOauth2 = window.ui.authActions.authorizeOauth2; + + window.ui.authActions.authorizeOauth2 = (payload) => { + // If the token can expire, schedule a token refresh and update the timer + if (payload.token.expires_in) { + const tokenRefreshTimeout = payload.token.expires_in * 750; + console.log( + `Refreshable token detected. Scheduling token refresh in ${( + tokenRefreshTimeout / + 1000 / + 60 + ).toFixed(1)}min (expires in ${(payload.token.expires_in / 60).toFixed( + 1, + )}min)...`, + ); + window.tokenRefreshTime = Date.now() + payload.token.expires_in * 750; + + // Start the clock + startClock(); + } + + return origAuthorizeOauth2(payload); + }; + + startClock(); +} + +patchRefreshHook(); diff --git a/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/resources/META-INF/resources/webjars/swagger-ui/index.html b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/resources/META-INF/resources/webjars/swagger-ui/index.html new file mode 100644 index 00000000000..c8b1013a57d --- /dev/null +++ b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/main/resources/META-INF/resources/webjars/swagger-ui/index.html @@ -0,0 +1,21 @@ + + + + + Swagger UI + + + + + + + +
+ + + + + + + + diff --git a/activiti-cloud-service-common/activiti-cloud-services-swagger/src/test/resources/org/activiti/cloud/common/swagger/apidocs/springdoc-api-docs.json b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/test/resources/org/activiti/cloud/common/swagger/apidocs/springdoc-api-docs.json index aa88a5edd1e..8c8a3bfa614 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-swagger/src/test/resources/org/activiti/cloud/common/swagger/apidocs/springdoc-api-docs.json +++ b/activiti-cloud-service-common/activiti-cloud-services-swagger/src/test/resources/org/activiti/cloud/common/swagger/apidocs/springdoc-api-docs.json @@ -483,6 +483,9 @@ "name": { "type": "string" }, + "static": { + "type": "boolean" + }, "public": { "type": "boolean" }, @@ -522,6 +525,24 @@ "title": "ExtendedJsonDeserializer", "type": "object", "properties": { + "nullValue": { + "uniqueItems": true, + "type": "array", + "deprecated": true, + "items": { + "$ref": "#/components/schemas/ExtendedJsonDeserializer" + } + }, + "cachable": { + "type": "boolean" + }, + "emptyValue": { + "type": "object", + "deprecated": true + }, + "delegatee": { + "$ref": "#/components/schemas/JsonDeserializerObject" + }, "knownPropertyNames": { "type": "array", "items": { @@ -544,24 +565,6 @@ "DYNAMIC" ] }, - "delegatee": { - "$ref": "#/components/schemas/JsonDeserializerObject" - }, - "cachable": { - "type": "boolean" - }, - "nullValue": { - "uniqueItems": true, - "type": "array", - "deprecated": true, - "items": { - "$ref": "#/components/schemas/ExtendedJsonDeserializer" - } - }, - "emptyValue": { - "type": "object", - "deprecated": true - }, "objectIdReader": { "$ref": "#/components/schemas/ObjectIdReader" }, @@ -587,6 +590,20 @@ "title": "JsonDeserializerObject", "type": "object", "properties": { + "nullValue": { + "type": "object", + "deprecated": true + }, + "cachable": { + "type": "boolean" + }, + "emptyValue": { + "type": "object", + "deprecated": true + }, + "delegatee": { + "$ref": "#/components/schemas/JsonDeserializerObject" + }, "knownPropertyNames": { "type": "array", "items": { @@ -609,20 +626,6 @@ "DYNAMIC" ] }, - "delegatee": { - "$ref": "#/components/schemas/JsonDeserializerObject" - }, - "cachable": { - "type": "boolean" - }, - "nullValue": { - "type": "object", - "deprecated": true - }, - "emptyValue": { - "type": "object", - "deprecated": true - }, "objectIdReader": { "$ref": "#/components/schemas/ObjectIdReader" } @@ -662,11 +665,11 @@ "title": "ObjectIdInfo", "type": "object", "properties": { - "propertyName": { - "$ref": "#/components/schemas/PropertyName" - }, "alwaysAsId": { "type": "boolean" + }, + "propertyName": { + "$ref": "#/components/schemas/PropertyName" } } }, @@ -709,9 +712,6 @@ "required": { "type": "boolean" }, - "description": { - "type": "string" - }, "mergeInfo": { "$ref": "#/components/schemas/MergeInfo" }, @@ -725,6 +725,9 @@ "DEFAULT" ] }, + "description": { + "type": "string" + }, "contentNulls": { "type": "string", "enum": [ @@ -762,52 +765,52 @@ "fullName": { "$ref": "#/components/schemas/PropertyName" }, - "ignorable": { - "type": "boolean" - }, "managedReferenceName": { "type": "string" }, - "objectIdInfo": { - "$ref": "#/components/schemas/ObjectIdInfo" - }, - "wrapperName": { - "$ref": "#/components/schemas/PropertyName" + "valueTypeDeserializer": { + "$ref": "#/components/schemas/TypeDeserializer" }, "member": { "$ref": "#/components/schemas/AnnotatedMember" }, - "valueTypeDeserializer": { - "$ref": "#/components/schemas/TypeDeserializer" + "wrapperName": { + "$ref": "#/components/schemas/PropertyName" }, - "injectableValueId": { - "type": "object" + "ignorable": { + "type": "boolean" + }, + "objectIdInfo": { + "$ref": "#/components/schemas/ObjectIdInfo" }, "nullValueProvider": { "$ref": "#/components/schemas/NullValueProvider" }, - "valueDeserializer": { - "$ref": "#/components/schemas/JsonDeserializerObject" - }, - "injectionOnly": { - "type": "boolean" - }, - "creatorIndex": { + "propertyIndex": { "type": "integer", "format": "int32" }, - "propertyIndex": { + "creatorIndex": { "type": "integer", "format": "int32" }, - "virtual": { + "injectableValueId": { + "type": "object" + }, + "injectionOnly": { "type": "boolean" }, - "metadata": { - "$ref": "#/components/schemas/PropertyMetadata" + "valueDeserializer": { + "$ref": "#/components/schemas/JsonDeserializerObject" + }, + "virtual": { + "type": "boolean" }, "required": { "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/PropertyMetadata" } } }, @@ -815,9 +818,6 @@ "title": "TypeDeserializer", "type": "object", "properties": { - "propertyName": { - "type": "string" - }, "typeInclusion": { "type": "string", "enum": [ @@ -828,6 +828,9 @@ "EXISTING_PROPERTY" ] }, + "propertyName": { + "type": "string" + }, "typeIdResolver": { "$ref": "#/components/schemas/TypeIdResolver" } @@ -837,9 +840,6 @@ "title": "TypeIdResolver", "type": "object", "properties": { - "descForKnownTypeIds": { - "type": "string" - }, "mechanism": { "type": "string", "enum": [ @@ -847,9 +847,13 @@ "CLASS", "MINIMAL_CLASS", "NAME", + "SIMPLE_NAME", "DEDUCTION", "CUSTOM" ] + }, + "descForKnownTypeIds": { + "type": "string" } } }, @@ -863,10 +867,9 @@ "type": "oauth2", "description": "Authorizing with SSO", "flows": { - "implicit": { + "authorizationCode": { "authorizationUrl": "http://dummy/token/url", - "scopes": { - } + "scopes": {} } } } diff --git a/activiti-cloud-service-common/activiti-cloud-services-test-containers/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-test-containers/pom.xml index c3119ae418b..02df2d88eea 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-test-containers/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-test-containers/pom.xml @@ -5,11 +5,14 @@ org.activiti.cloud activiti-cloud-service-common-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-test-containers Activiti Cloud Services :: Test Containers + + 3.3.1 + org.testcontainers @@ -18,7 +21,7 @@ com.github.dasniko testcontainers-keycloak - 2.2.2 + ${testcontainers-keycloak.version} org.springframework @@ -28,5 +31,10 @@ org.springframework.boot spring-boot-test + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/main/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializer.java b/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/main/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializer.java index 0b198c597d2..eaecb483e50 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/main/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializer.java +++ b/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/main/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializer.java @@ -25,7 +25,7 @@ public class KeycloakContainerApplicationInitializer implements ApplicationContextInitializer { - private static KeycloakContainer keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:18.0.0") + private static KeycloakContainer keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:24.0.3") .withAdminUsername("admin") .withAdminPassword("admin") .withRealmImportFile("activiti-realm.json") diff --git a/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/test/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializerIT.java b/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/test/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializerIT.java new file mode 100644 index 00000000000..a2065f45782 --- /dev/null +++ b/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/test/java/org/activiti/cloud/services/test/containers/KeycloakContainerApplicationInitializerIT.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.test.containers; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest(classes = { TestContainersApplication.class }) +@ContextConfiguration(initializers = { KeycloakContainerApplicationInitializer.class }) +class KeycloakContainerApplicationInitializerIT { + + @Test + void contextLoads() { + // application context loads successfully + } +} diff --git a/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/test/java/org/activiti/cloud/services/test/containers/TestContainersApplication.java b/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/test/java/org/activiti/cloud/services/test/containers/TestContainersApplication.java new file mode 100644 index 00000000000..ceadabdc8ad --- /dev/null +++ b/activiti-cloud-service-common/activiti-cloud-services-test-containers/src/test/java/org/activiti/cloud/services/test/containers/TestContainersApplication.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017-2020 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.activiti.cloud.services.test.containers; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TestContainersApplication { + + public static void main(String[] args) { + SpringApplication.run(TestContainersApplication.class, args); + } +} diff --git a/activiti-cloud-service-common/activiti-cloud-services-test-security/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-test-security/pom.xml index 8f7eb44af0b..9f42f76e5da 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-test-security/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-test-security/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-test-security diff --git a/activiti-cloud-service-common/activiti-cloud-services-test/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-test/pom.xml index b16249b5ec9..9a50e6d94d8 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-test/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-test/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-service-common-dependencies - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-test diff --git a/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java b/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java index 86d82566b71..45891b4b847 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java +++ b/activiti-cloud-service-common/activiti-cloud-services-test/src/main/java/org/activiti/cloud/starters/test/builder/ProcessInstanceEventContainedBuilder.java @@ -166,6 +166,17 @@ public ProcessInstanceImpl aRunningProcessInstanceWithAppVersion(String name, St return processInstance; } + public ProcessInstanceImpl aCompletedProcessInstanceWithAppVersion(String name, String appVersion) { + ProcessInstanceImpl processInstance = buildProcessInstance(name); + processInstance.setAppVersion(appVersion); + eventsAggregator.addEvents( + new CloudProcessCreatedEventImpl(processInstance), + new CloudProcessStartedEventImpl(processInstance), + new CloudProcessCompletedEventImpl(processInstance) + ); + return processInstance; + } + public CloudProcessInstanceImpl aRunningProcessInstanceWithSuspendedDate(String name, Date suspendedDate) { CloudProcessInstanceImpl suspendedProcess = buildSuspendedProcessInstance(name); suspendedProcess.setSuspendedDate(suspendedDate); diff --git a/activiti-cloud-service-common/activiti-cloud-services-tracing/pom.xml b/activiti-cloud-service-common/activiti-cloud-services-tracing/pom.xml index c4a0181389f..9c3e583f0d9 100644 --- a/activiti-cloud-service-common/activiti-cloud-services-tracing/pom.xml +++ b/activiti-cloud-service-common/activiti-cloud-services-tracing/pom.xml @@ -5,7 +5,7 @@ activiti-cloud-service-common-dependencies org.activiti.cloud - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-service-common-dependencies activiti-cloud-services-tracing diff --git a/activiti-cloud-service-common/pom.xml b/activiti-cloud-service-common/pom.xml index 6564e6f938e..cc72239f79a 100644 --- a/activiti-cloud-service-common/pom.xml +++ b/activiti-cloud-service-common/pom.xml @@ -5,7 +5,7 @@ org.activiti.cloud activiti-cloud-build-parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT ../activiti-cloud-build activiti-cloud-service-common-parent @@ -34,7 +34,7 @@ activiti-cloud-service-messaging-starter - 8.5.0-alpha.4 + 8.7.0-alpha.27 1.9.4 1.10 2.6 @@ -47,7 +47,7 @@ 2.36.0 4.4.0 - 0.8.9 + 0.8.11 1.17 1.5 diff --git a/pom.xml b/pom.xml index e6d0d7623db..9a1373e918d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ activiti-cloud-mono-aggregator pom Activiti Cloud Mono :: Parent - 8.6.0-SNAPSHOT + 8.7.0-SNAPSHOT Activiti Cloud Mono :: Aggregator http://activiti.org 2017 @@ -195,7 +195,7 @@ activiti-cloud 2020 - 3.2.5 + 3.3.4 ${project.build.directory}/generated-test-sources/assertions @@ -221,7 +221,10 @@ 3.11.0 3.2.1 2.22.2 - 6.3.1.Final + + + 6.5.3.Final + 4.8.175