From 3feccd234eb90229ff4887db845e87a37d0df9f7 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Thu, 6 Jun 2024 02:21:49 +0000 Subject: [PATCH 01/49] Update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.4.0 --- pom.xml | 2 +- template-placeholder-demo/pom.xml | 2 +- template-placeholder/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 5da2110b..8fc5ca96 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.4.0 true diff --git a/template-placeholder-demo/pom.xml b/template-placeholder-demo/pom.xml index f40d02ef..326f855c 100644 --- a/template-placeholder-demo/pom.xml +++ b/template-placeholder-demo/pom.xml @@ -85,7 +85,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.4.0 com.puppycrawl.tools diff --git a/template-placeholder/pom.xml b/template-placeholder/pom.xml index 539a8a01..fb307dd4 100644 --- a/template-placeholder/pom.xml +++ b/template-placeholder/pom.xml @@ -242,7 +242,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.4.0 com.puppycrawl.tools From 544753bfbed0449cbc29d0926f09d27bbcb55fc2 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 15:59:00 +0200 Subject: [PATCH 02/49] Fix rev-parse not working --- .github/workflows/update-from-template.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 756607dc..4bba6aa2 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -183,8 +183,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - # Required because otherwise there are always changes detected when executing diff/rev-list - fetch-depth: 0 # If no PAT is used the following error occurs on a push: # refusing to allow a GitHub App to create or update workflow `.github/workflows/xxx.yml` without `workflows` permission token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} From 49f82a1418e2de0ccdd209b8682fcd32620d1802 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 16:14:47 +0200 Subject: [PATCH 03/49] Fix problem with fetch depth of 0 --- .github/workflows/update-from-template.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 4bba6aa2..235ac3f0 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -183,6 +183,8 @@ jobs: steps: - uses: actions/checkout@v4 with: + # Required because otherwise there are always changes detected when executing diff/rev-list + fetch-depth: 0 # If no PAT is used the following error occurs on a push: # refusing to allow a GitHub App to create or update workflow `.github/workflows/xxx.yml` without `workflows` permission token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} @@ -208,7 +210,7 @@ jobs: echo "Checking if update-branch-merged exists" git fetch - if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + if [[ $(git ls-remote --exit-code --heads origin ${{ env.UPDATE_BRANCH_MERGED }}) ]]; then echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 fi @@ -269,8 +271,11 @@ jobs: base_branch=$(git branch --show-current) echo "Base branch is $base_branch" - echo "Fetching..." - git fetch + echo "Fully fetching..." + git fetch --unshallow || true + git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + git fetch origin + if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 From 1b8b6b20e4726f16762b36ba8b8eaa9d92513216 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 16:26:17 +0200 Subject: [PATCH 04/49] Fully unshallow every as ls-remote also fails --- .github/workflows/update-from-template.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 235ac3f0..7a07bc69 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -209,8 +209,9 @@ jobs: echo "Checking if PR can be auto-merged. Try: $i" echo "Checking if update-branch-merged exists" - git fetch - if [[ $(git ls-remote --exit-code --heads origin ${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + git fetch --unshallow && git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" || true + git fetch origin + if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 fi @@ -272,8 +273,7 @@ jobs: echo "Base branch is $base_branch" echo "Fully fetching..." - git fetch --unshallow || true - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + git fetch --unshallow && git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" || true git fetch origin if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then From 538caf18362b0f16b17a492e02193073bf6a61f3 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 16:36:56 +0200 Subject: [PATCH 05/49] Revert "Fully unshallow every as ls-remote also fails" This reverts commit 1b8b6b20e4726f16762b36ba8b8eaa9d92513216. --- .github/workflows/update-from-template.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 7a07bc69..235ac3f0 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -209,9 +209,8 @@ jobs: echo "Checking if PR can be auto-merged. Try: $i" echo "Checking if update-branch-merged exists" - git fetch --unshallow && git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" || true - git fetch origin - if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + git fetch + if [[ $(git ls-remote --exit-code --heads origin ${{ env.UPDATE_BRANCH_MERGED }}) ]]; then echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 fi @@ -273,7 +272,8 @@ jobs: echo "Base branch is $base_branch" echo "Fully fetching..." - git fetch --unshallow && git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" || true + git fetch --unshallow || true + git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" git fetch origin if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then From ca909f162c7505f5fc2db36c7e3b00dc91004b0e Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 16:37:01 +0200 Subject: [PATCH 06/49] Revert "Fix problem with fetch depth of 0" This reverts commit 49f82a1418e2de0ccdd209b8682fcd32620d1802. --- .github/workflows/update-from-template.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 235ac3f0..4bba6aa2 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -183,8 +183,6 @@ jobs: steps: - uses: actions/checkout@v4 with: - # Required because otherwise there are always changes detected when executing diff/rev-list - fetch-depth: 0 # If no PAT is used the following error occurs on a push: # refusing to allow a GitHub App to create or update workflow `.github/workflows/xxx.yml` without `workflows` permission token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} @@ -210,7 +208,7 @@ jobs: echo "Checking if update-branch-merged exists" git fetch - if [[ $(git ls-remote --exit-code --heads origin ${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 fi @@ -271,11 +269,8 @@ jobs: base_branch=$(git branch --show-current) echo "Base branch is $base_branch" - echo "Fully fetching..." - git fetch --unshallow || true - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" - git fetch origin - + echo "Fetching..." + git fetch if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 From 38e37eb825c282f05f573b687027e07c8fef039f Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 16:37:05 +0200 Subject: [PATCH 07/49] Revert "Fix rev-parse not working" This reverts commit 544753bfbed0449cbc29d0926f09d27bbcb55fc2. --- .github/workflows/update-from-template.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 4bba6aa2..756607dc 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -183,6 +183,8 @@ jobs: steps: - uses: actions/checkout@v4 with: + # Required because otherwise there are always changes detected when executing diff/rev-list + fetch-depth: 0 # If no PAT is used the following error occurs on a push: # refusing to allow a GitHub App to create or update workflow `.github/workflows/xxx.yml` without `workflows` permission token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }} From 56ef08ae9bb3602a486543843dd0e8b5f09bb72e Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 11 Jun 2024 16:38:49 +0200 Subject: [PATCH 08/49] Correct if --- .github/workflows/update-from-template.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 756607dc..ba0bf090 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -211,6 +211,8 @@ jobs: echo "Checking if update-branch-merged exists" git fetch if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + echo "Branch still exists; Continuing..." + else echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 fi @@ -274,6 +276,8 @@ jobs: echo "Fetching..." git fetch if [[ $(git rev-parse origin/${{ env.UPDATE_BRANCH_MERGED }}) ]]; then + echo "Branch still exists; Continuing..." + else echo "Branch origin/${{ env.UPDATE_BRANCH_MERGED }} is missing" exit 0 fi From 03dd57153ee758d4354a4fad9663e974dfb14e24 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Mon, 17 Jun 2024 02:25:02 +0000 Subject: [PATCH 09/49] Update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.6.0 --- template-placeholder/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template-placeholder/pom.xml b/template-placeholder/pom.xml index fb307dd4..5030ab19 100644 --- a/template-placeholder/pom.xml +++ b/template-placeholder/pom.xml @@ -95,7 +95,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.5.0 + 3.6.0 From 7e57677633459ccd76d4f41e9ae9d4a1b7476721 Mon Sep 17 00:00:00 2001 From: XDEV Bot <111048771+xdev-gh-bot@users.noreply.github.com> Date: Mon, 17 Jun 2024 02:57:50 +0000 Subject: [PATCH 10/49] Fill in template --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 ++-- .github/ISSUE_TEMPLATE/enhancement.yml | 2 +- .github/ISSUE_TEMPLATE/question.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 68299d5d..041c89bc 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -14,9 +14,9 @@ body: attributes: label: "Checklist" options: - - label: "I am able to reproduce the bug with the [latest version](https://github.com/xdev-software/template-placeholder/releases/latest)" + - label: "I am able to reproduce the bug with the [latest version](https://github.com/xdev-software/spring-data-eclipse-store/releases/latest)" required: true - - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/template-placeholder/issues) or [closed](https://github.com/xdev-software/template-placeholder/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/spring-data-eclipse-store/issues) or [closed](https://github.com/xdev-software/spring-data-eclipse-store/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." required: true - label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise." required: true diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 75231293..4ed79471 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -12,7 +12,7 @@ body: attributes: label: "Checklist" options: - - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/template-placeholder/issues) or [closed](https://github.com/xdev-software/template-placeholder/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/spring-data-eclipse-store/issues) or [closed](https://github.com/xdev-software/spring-data-eclipse-store/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." required: true - label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise." required: true diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index 6ecd6ad5..05f66d4b 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -12,7 +12,7 @@ body: attributes: label: "Checklist" options: - - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/template-placeholder/issues) or [closed](https://github.com/xdev-software/template-placeholder/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." + - label: "I made sure that there are *no existing issues* - [open](https://github.com/xdev-software/spring-data-eclipse-store/issues) or [closed](https://github.com/xdev-software/spring-data-eclipse-store/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to." required: true - label: "I have taken the time to fill in all the required details. I understand that the question will be dismissed otherwise." required: true From 7313ce9b3960ac6cbca4f6b5e16d211463164bf8 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Tue, 18 Jun 2024 02:23:41 +0000 Subject: [PATCH 11/49] Update dependency maven to v3.9.8 --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index f800e78d..e56bc180 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,4 +14,4 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.8/apache-maven-3.9.8-bin.zip From 3e41f58521ab545319736284844e1784e678e4a4 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 18 Jun 2024 16:46:50 +0200 Subject: [PATCH 12/49] Add default PMD ruleset Co-Authored-By: ds-xdev <85935842+ds-xdev@users.noreply.github.com> --- .config/pmd/ruleset.xml | 149 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 .config/pmd/ruleset.xml diff --git a/.config/pmd/ruleset.xml b/.config/pmd/ruleset.xml new file mode 100644 index 00000000..02f64d79 --- /dev/null +++ b/.config/pmd/ruleset.xml @@ -0,0 +1,149 @@ + + + + + This ruleset checks the code for discouraged programming constructs. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 43ddc48eac02aeaea23d332fd4c88bebf9e0c4f8 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 18 Jun 2024 16:56:51 +0200 Subject: [PATCH 13/49] Attach demo to parent --- template-placeholder-demo/pom.xml | 39 +++++-------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/template-placeholder-demo/pom.xml b/template-placeholder-demo/pom.xml index 326f855c..1af633cf 100644 --- a/template-placeholder-demo/pom.xml +++ b/template-placeholder-demo/pom.xml @@ -4,7 +4,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - software.xdev + + software.xdev + template-placeholder-root + 1.0.0-SNAPSHOT + + template-placeholder-demo 1.0.0-SNAPSHOT jar @@ -77,36 +82,4 @@ - - - checkstyle - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.4.0 - - - com.puppycrawl.tools - checkstyle - 10.17.0 - - - - ../.config/checkstyle/checkstyle.xml - true - - - - - check - - - - - - - - From 3bc085a454ffefea389f3d3519e13445d97b60ef Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 18 Jun 2024 16:57:26 +0200 Subject: [PATCH 14/49] Reconfigure root and add pmd --- pom.xml | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8fc5ca96..3a04c7a3 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,11 @@ template-placeholder-demo + + UTF-8 + UTF-8 + + Apache License, Version 2.0 @@ -29,7 +34,6 @@ - checkstyle @@ -37,12 +41,67 @@ org.apache.maven.plugins maven-checkstyle-plugin 3.4.0 + + + com.puppycrawl.tools + checkstyle + 10.17.0 + + + + .config/checkstyle/checkstyle.xml + true + + + + + check + + + + + + + + + pmd + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.23.0 - true + true + + .config/pmd/ruleset.xml + + + + net.sourceforge.pmd + pmd-core + 7.2.0 + + + net.sourceforge.pmd + pmd-java + 7.2.0 + + + + + + + org.apache.maven.plugins + maven-jxr-plugin + 3.4.0 + + + From f5240c0ba9f96827abdd6c76d072883bda47edec Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 18 Jun 2024 16:57:44 +0200 Subject: [PATCH 15/49] Add pmd to published module --- template-placeholder/pom.xml | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/template-placeholder/pom.xml b/template-placeholder/pom.xml index 5030ab19..05a241f9 100644 --- a/template-placeholder/pom.xml +++ b/template-placeholder/pom.xml @@ -265,5 +265,45 @@ + + pmd + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.23.0 + + true + + ../.config/pmd/ruleset.xml + + + + + net.sourceforge.pmd + pmd-core + 7.2.0 + + + net.sourceforge.pmd + pmd-java + 7.2.0 + + + + + + + + + + org.apache.maven.plugins + maven-jxr-plugin + 3.4.0 + + + + From 11c6f7e9bd7a831a0929da58d4143406f95eeede Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 18 Jun 2024 16:59:00 +0200 Subject: [PATCH 16/49] Add pmd to check-build workflow --- .github/workflows/check-build.yml | 39 ++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index fa9b7f5d..2ac65305 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -70,7 +70,7 @@ jobs: path: ${{ env.DEMO_MAVEN_MODULE }}/target/${{ env.DEMO_MAVEN_MODULE }}.jar if-no-files-found: error - code-style: + checkstyle: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/') }} @@ -91,3 +91,40 @@ jobs: - name: Run Checkstyle run: ./mvnw -B checkstyle:check -P checkstyle -T2C + + pmd: + runs-on: ubuntu-latest + if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/') }} + + strategy: + matrix: + java: [17] + distribution: [temurin] + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: ${{ matrix.distribution }} + java-version: ${{ matrix.java }} + cache: 'maven' + + - name: Run PMD + run: ./mvnw -B test pmd:aggregate-pmd-no-fork pmd:check -P pmd -DskipTests -T2C + + - name: Run CPD (Copy Paste Detector) + run: ./mvnw -B pmd:aggregate-cpd pmd:cpd-check -P pmd -DskipTests -T2C + + - name: Upload report + if: always() + uses: actions/upload-artifact@v4 + with: + name: pmd-report + if-no-files-found: ignore + path: | + target/site/*.html + target/site/css/** + target/site/images/logos/maven-feather.png + target/site/images/external.png From d979ab94bb0a290219aef5cfbd97625843b93a8d Mon Sep 17 00:00:00 2001 From: AB Date: Wed, 19 Jun 2024 08:41:49 +0200 Subject: [PATCH 17/49] PMD: printFailingErrors --- pom.xml | 1 + template-placeholder/pom.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 3a04c7a3..e41a6a22 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,7 @@ 3.23.0 true + true .config/pmd/ruleset.xml diff --git a/template-placeholder/pom.xml b/template-placeholder/pom.xml index 05a241f9..b743ae74 100644 --- a/template-placeholder/pom.xml +++ b/template-placeholder/pom.xml @@ -275,6 +275,7 @@ 3.23.0 true + true ../.config/pmd/ruleset.xml From eed3d8aa02516e03553f39e83875b3776ce87240 Mon Sep 17 00:00:00 2001 From: AB Date: Wed, 19 Jun 2024 13:02:11 +0200 Subject: [PATCH 18/49] Update ruleset.xml --- .config/pmd/ruleset.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/pmd/ruleset.xml b/.config/pmd/ruleset.xml index 02f64d79..5f881567 100644 --- a/.config/pmd/ruleset.xml +++ b/.config/pmd/ruleset.xml @@ -135,6 +135,9 @@ + + + From 17a7371d4475666c075f6469b0344b482a7255dc Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 19 Jun 2024 14:04:09 +0200 Subject: [PATCH 19/49] Removed broken link --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 675d9cb7..894483a3 100644 --- a/README.md +++ b/README.md @@ -82,4 +82,5 @@ use [our support](https://xdev.software/en/services/support). See the [contributing guide](./CONTRIBUTING.md) for detailed instructions on how to get started with our project. ## Dependencies and Licenses -View the [license of the current project](LICENSE) or the [summary including all dependencies](https://xdev-software.github.io/spring-data-eclipse-store/dependencies) + +View the [license of the current project](LICENSE). From baeabdd28a8f371960cffde4d7fb32a833a1b7b7 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Wed, 19 Jun 2024 13:15:55 +0000 Subject: [PATCH 20/49] Update dependency maven to v3.9.8 --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index f800e78d..e56bc180 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,4 +14,4 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.8/apache-maven-3.9.8-bin.zip From 6eb1baad9bd74ee1172b2d1081f5b652ae6e1d7f Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Wed, 19 Jun 2024 13:15:56 +0000 Subject: [PATCH 21/49] Update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.6.0 --- spring-data-eclipse-store/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index 8ebdb428..69f8167d 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -202,7 +202,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.5.0 + 3.6.0 From eaf1d962c0df01160ed044698cb2982f124619a9 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Wed, 19 Jun 2024 13:15:58 +0000 Subject: [PATCH 22/49] Update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.3.0 --- spring-data-eclipse-store/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index 8ebdb428..b1811012 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -269,7 +269,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 --add-opens java.base/java.util=ALL-UNNAMED From 6a258c70a5b6a423ca90196e79f0b37a2a2302b3 Mon Sep 17 00:00:00 2001 From: Alex B <45384811+AB-xdev@users.noreply.github.com> Date: Thu, 20 Jun 2024 09:02:41 +0200 Subject: [PATCH 23/49] Remove duplicate in .gitignore --- .gitignore | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.gitignore b/.gitignore index d0e81bf1..116a656e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,11 +39,6 @@ buildNumber.properties # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* - -# bin / compiled stuff -target/ - - # JRebel **/resources/rebel.xml **/resources/rebel-remote.xml From b8fa58ad362cc7068206d7dcbb5cb6c2f62bc128 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Fri, 21 Jun 2024 02:21:32 +0000 Subject: [PATCH 24/49] Update org.springframework.boot.version to v3.3.1 --- spring-data-eclipse-store-benchmark/pom.xml | 2 +- spring-data-eclipse-store-demo/pom.xml | 2 +- spring-data-eclipse-store-jpa/pom.xml | 2 +- spring-data-eclipse-store/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-data-eclipse-store-benchmark/pom.xml b/spring-data-eclipse-store-benchmark/pom.xml index 911fd26b..45948046 100644 --- a/spring-data-eclipse-store-benchmark/pom.xml +++ b/spring-data-eclipse-store-benchmark/pom.xml @@ -20,7 +20,7 @@ UTF-8 UTF-8 - 3.2.5 + 3.3.1 1.37 diff --git a/spring-data-eclipse-store-demo/pom.xml b/spring-data-eclipse-store-demo/pom.xml index 372f2fcc..93562970 100644 --- a/spring-data-eclipse-store-demo/pom.xml +++ b/spring-data-eclipse-store-demo/pom.xml @@ -23,7 +23,7 @@ software.xdev.spring.data.eclipse.store.demo.complex.ComplexDemoApplication - 3.2.5 + 3.3.1 diff --git a/spring-data-eclipse-store-jpa/pom.xml b/spring-data-eclipse-store-jpa/pom.xml index b1ac0322..eb40b38e 100644 --- a/spring-data-eclipse-store-jpa/pom.xml +++ b/spring-data-eclipse-store-jpa/pom.xml @@ -25,7 +25,7 @@ software.xdev.spring.data.eclipse.store.demo.complex.ComplexDemoApplication - 3.2.5 + 3.3.1 diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index 8ebdb428..183489bc 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -50,7 +50,7 @@ UTF-8 - 3.2.5 + 3.3.1 1.3.2 1.3.2 From f2290e689466bac63811f4ca96b6069ec1f9c8ee Mon Sep 17 00:00:00 2001 From: AB Date: Mon, 24 Jun 2024 08:34:54 +0200 Subject: [PATCH 25/49] Ignore project internal depenedencies --- renovate.json5 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/renovate.json5 b/renovate.json5 index 11a77b2a..11024f46 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -1,4 +1,14 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "rebaseWhen": "behind-base-branch" + "rebaseWhen": "behind-base-branch", + "packageRules": [ + { + "description": "Ignore project internal dependencies", + "packagePattern": "^software.xdev:template-placeholder", + "datasources": [ + "maven" + ], + "enabled": false + } + ] } From 19615bac94799a582a7aeeed215c338ab5fa1593 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Tue, 25 Jun 2024 15:22:32 +0200 Subject: [PATCH 26/49] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 894483a3..d1654ce1 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,8 @@ instructions** are in the documentation](https://xdev-software.github.io/spring- |---------------------------|--------|-------------|--------------| | ``<= 1.0.2`` | ``17`` | ``3.2.2`` | ``1.1.0`` | | ``1.0.3/1.0.4`` | ``17`` | ``3.2.3`` | ``1.2.0`` | -| ``>= 1.0.5`` | ``17`` | ``3.2.5`` | ``1.3.2`` | +| ``1.0.5-1.0.7`` | ``17`` | ``3.2.5`` | ``1.3.2`` | +| ``>= 1.0.8`` | ``17`` | ``3.3.1`` | ``1.3.2`` | ## Demo From baca58cd6501c8ad284e2599c7e53bf521457766 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 25 Jun 2024 15:41:50 +0200 Subject: [PATCH 27/49] Fill in template --- renovate.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json5 b/renovate.json5 index 11024f46..0c1deaad 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -4,7 +4,7 @@ "packageRules": [ { "description": "Ignore project internal dependencies", - "packagePattern": "^software.xdev:template-placeholder", + "packagePattern": "^software.xdev:spring-data-eclipse-store", "datasources": [ "maven" ], From 4cb2fdcd071ba5c2fc3db35ab9711ff8c4d2fddb Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 25 Jun 2024 15:42:06 +0200 Subject: [PATCH 28/49] Handle other demos like demo project --- spring-data-eclipse-store-benchmark/pom.xml | 38 ++++----------------- spring-data-eclipse-store-jpa/pom.xml | 38 ++++----------------- 2 files changed, 12 insertions(+), 64 deletions(-) diff --git a/spring-data-eclipse-store-benchmark/pom.xml b/spring-data-eclipse-store-benchmark/pom.xml index 45948046..edb74829 100644 --- a/spring-data-eclipse-store-benchmark/pom.xml +++ b/spring-data-eclipse-store-benchmark/pom.xml @@ -2,7 +2,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.xdev-software + + software.xdev + spring-data-eclipse-store-root + 1.0.8-SNAPSHOT + + spring-data-eclipse-store-benchmark 1.0.8-SNAPSHOT jar @@ -83,35 +88,4 @@ - - - checkstyle - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.4.0 - - - com.puppycrawl.tools - checkstyle - 10.17.0 - - - - ../.config/checkstyle/checkstyle.xml - - - - - check - - - - - - - - diff --git a/spring-data-eclipse-store-jpa/pom.xml b/spring-data-eclipse-store-jpa/pom.xml index eb40b38e..404a5462 100644 --- a/spring-data-eclipse-store-jpa/pom.xml +++ b/spring-data-eclipse-store-jpa/pom.xml @@ -4,7 +4,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - software.xdev + + software.xdev + spring-data-eclipse-store-root + 1.0.8-SNAPSHOT + + spring-data-eclipse-store-jpa 1.0.8-SNAPSHOT jar @@ -110,35 +115,4 @@ - - - checkstyle - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.4.0 - - - com.puppycrawl.tools - checkstyle - 10.17.0 - - - - ../.config/checkstyle/checkstyle.xml - - - - - check - - - - - - - - From b66dde8203efd9c3fca166566a3a47af617d5582 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 25 Jun 2024 15:43:39 +0200 Subject: [PATCH 29/49] Fix conflict in parent pom --- pom.xml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 51136218..65a2c800 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,9 @@ 17 ${javaVersion} + + UTF-8 + UTF-8 @@ -26,11 +29,6 @@ spring-data-eclipse-store-jpa - - UTF-8 - UTF-8 - - Apache License, Version 2.0 From c9bc5c5cb0a83a05f0405760222b5ebbf5e0e2c9 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 25 Jun 2024 15:50:37 +0200 Subject: [PATCH 30/49] Fix format How many times do I have to tell to use our standard which is tabs? --- spring-data-eclipse-store-benchmark/pom.xml | 148 ++++++++++---------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/spring-data-eclipse-store-benchmark/pom.xml b/spring-data-eclipse-store-benchmark/pom.xml index edb74829..1ab40c77 100644 --- a/spring-data-eclipse-store-benchmark/pom.xml +++ b/spring-data-eclipse-store-benchmark/pom.xml @@ -1,91 +1,91 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - + software.xdev spring-data-eclipse-store-root 1.0.8-SNAPSHOT - spring-data-eclipse-store-benchmark - 1.0.8-SNAPSHOT - jar + spring-data-eclipse-store-benchmark + 1.0.8-SNAPSHOT + jar - 2023 + 2023 - - XDEV Software - https://xdev.software - + + XDEV Software + https://xdev.software + - - 17 - ${javaVersion} - UTF-8 - UTF-8 + + 17 + ${javaVersion} + UTF-8 + UTF-8 - 3.3.1 - 1.37 - + 3.3.1 + 1.37 + - - - - org.springframework.boot - spring-boot-dependencies - ${org.springframework.boot.version} - pom - import - - - + + + + org.springframework.boot + spring-boot-dependencies + ${org.springframework.boot.version} + pom + import + + + - - - software.xdev - spring-data-eclipse-store - ${project.version} - + + + software.xdev + spring-data-eclipse-store + ${project.version} + - - org.springframework.boot - spring-boot - - - org.springframework.boot - spring-boot-starter - + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-starter + - - org.openjdk.jmh - jmh-core - ${jmh.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - - + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - ${maven.compiler.release} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - - - - - - + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${maven.compiler.release} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + + From 93a7f4ebc08ea8f664d84cfdfa7570214fa871d9 Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 25 Jun 2024 16:14:11 +0200 Subject: [PATCH 31/49] Fix PMD Co-Authored-By: Johannes Rabauer <8188460+JohannesRabauer@users.noreply.github.com> --- .../integration/JpaImportExplicitTest.java | 2 +- .../exceptions/NotComparableException.java | 5 + .../lazy/SpringDataEclipseStoreLazy.java | 4 +- .../query/EclipseStoreQueryCreator.java | 1 + .../query/criteria/CriteriaByExample.java | 103 ++++++++++-------- .../query/executors/EntitySorter.java | 5 +- .../EclipseStoreRepositoryFactoryBean.java | 2 +- .../SimpleRepositorySynchronizer.java | 11 +- .../EclipseStoreTransactionManager.java | 9 +- .../tests/special/types/LazyDaoObject.java | 2 + .../tests/special/types/TypesData.java | 1 + 11 files changed, 81 insertions(+), 64 deletions(-) diff --git a/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportExplicitTest.java b/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportExplicitTest.java index daaaf988..70e452fb 100644 --- a/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportExplicitTest.java +++ b/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportExplicitTest.java @@ -49,7 +49,7 @@ class JpaImportExplicitTest private EclipseStoreClientConfiguration configuration; @Test - void testEclipseStoreImport_ExplicitNoComponent() + void testEclipseStoreImportExplicitNoComponent() { final PersonToTestInJpa customer = new PersonToTestInJpa("", ""); this.personToTestInJpaRepository.save(customer); diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/exceptions/NotComparableException.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/exceptions/NotComparableException.java index b5fe9aa1..26611997 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/exceptions/NotComparableException.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/exceptions/NotComparableException.java @@ -21,4 +21,9 @@ public NotComparableException(final String message) { super(message); } + + public NotComparableException(final String message, final Throwable cause) + { + super(message, cause); + } } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/lazy/SpringDataEclipseStoreLazy.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/lazy/SpringDataEclipseStoreLazy.java index 2d745474..2d29d410 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/lazy/SpringDataEclipseStoreLazy.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/lazy/SpringDataEclipseStoreLazy.java @@ -64,8 +64,8 @@ static SpringDataEclipseStoreLazy.Default buildWithLazy(final Lazy laz * * @param the type of the lazily referenced element */ - @SuppressWarnings({"java:S2065", "checkstyle:FinalClass"}) - class Default implements SpringDataEclipseStoreLazy + @SuppressWarnings({"java:S2065"}) + final class Default implements SpringDataEclipseStoreLazy { private T objectToBeWrapped; private Lazy wrappedLazy; diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/EclipseStoreQueryCreator.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/EclipseStoreQueryCreator.java index 341afd13..8f1ade91 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/EclipseStoreQueryCreator.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/EclipseStoreQueryCreator.java @@ -118,6 +118,7 @@ protected QueryExecutor complete(final AbstractCriteriaNode criteria, @Non return QueryExecutorCreator.createQuery(this.typeInformation, this.copier, criteria, sort); } + @SuppressWarnings("PMD.CyclomaticComplexity") private AbstractCriteriaNode from( final Part part, final AbstractCriteriaNode criteria, diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java index e6b4d988..01479075 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java @@ -107,64 +107,77 @@ private Predicate createPredicateForSpecif ? example.getMatcher().getDefaultStringMatcher() : specifier.getStringMatcher(); - switch(setOrDefaultMatcher) + return this.createPredicateForStringMatcher( + specifier, + setOrDefaultMatcher, + transformedExampledValue, + transformedValue); + }; + } + + private boolean createPredicateForStringMatcher( + final ExampleMatcher.PropertySpecifier specifier, + final ExampleMatcher.StringMatcher setOrDefaultMatcher, + final Optional transformedExampledValue, + final Optional transformedValue) + { + switch(setOrDefaultMatcher) + { + case DEFAULT, EXACT -> { - case DEFAULT, EXACT -> + if(transformedExampledValue.get() instanceof String) { - if(transformedExampledValue.get() instanceof String) - { - return this.valueToString(transformedValue, specifier).equals(this.valueToString( - transformedExampledValue, - specifier)); - } - return transformedExampledValue.equals(transformedValue); + return this.valueToString(transformedValue, specifier).equals(this.valueToString( + transformedExampledValue, + specifier)); } - case STARTING -> - { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return valueAsString.get() - .startsWith(this.valueToString(transformedExampledValue, specifier).get()); - } - case ENDING -> + return transformedExampledValue.equals(transformedValue); + } + case STARTING -> + { + final Optional valueAsString = this.valueToString(transformedValue, specifier); + if(valueAsString.isEmpty()) { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return valueAsString.get().endsWith(this.valueToString(transformedExampledValue, specifier).get()); + return false; } - case CONTAINING -> + return valueAsString.get() + .startsWith(this.valueToString(transformedExampledValue, specifier).get()); + } + case ENDING -> + { + final Optional valueAsString = this.valueToString(transformedValue, specifier); + if(valueAsString.isEmpty()) { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return valueAsString.get().contains(this.valueToString(transformedExampledValue, specifier).get()); + return false; } - case REGEX -> + return valueAsString.get().endsWith(this.valueToString(transformedExampledValue, specifier).get()); + } + case CONTAINING -> + { + final Optional valueAsString = this.valueToString(transformedValue, specifier); + if(valueAsString.isEmpty()) { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return Pattern.compile( - this.valueToString(transformedExampledValue, specifier).get() - ) - .matcher(valueAsString.get()).find(); + return false; } - default -> + return valueAsString.get().contains(this.valueToString(transformedExampledValue, specifier).get()); + } + case REGEX -> + { + final Optional valueAsString = this.valueToString(transformedValue, specifier); + if(valueAsString.isEmpty()) { return false; } + return Pattern.compile( + this.valueToString(transformedExampledValue, specifier).get() + ) + .matcher(valueAsString.get()).find(); } - }; + default -> + { + return false; + } + } } private Optional valueToString( diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/executors/EntitySorter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/executors/EntitySorter.java index 48d7e5d9..82968624 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/executors/EntitySorter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/executors/EntitySorter.java @@ -48,9 +48,8 @@ public static Stream sortEntitiesStream(final Class clazz, final Sort } catch(final NoSuchFieldException e) { - throw new NotComparableException(String.format( - "Could not sort entities by property %s", - order.getProperty())); + throw new NotComparableException( + "Could not sort entities by property " + order.getProperty(), e); } } } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactoryBean.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactoryBean.java index ecec7407..e98bc944 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactoryBean.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactoryBean.java @@ -67,7 +67,7 @@ public void setConfigurationClass(final Class configurationClass) } @Override - public void setBeanFactory(final BeanFactory beanFactory) throws BeansException + public void setBeanFactory(final BeanFactory beanFactory) { super.setBeanFactory(beanFactory); this.beanFactory = beanFactory; diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java index 7a4ee4ed..81b16a28 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java @@ -51,14 +51,11 @@ public SimpleRepositorySynchronizer(final Root root) } final Class objectInGraphClass = (Class)objectInGraph.getClass(); final IdentitySet entityListForCurrentObject = this.root.getEntityList(objectInGraphClass); - if(entityListForCurrentObject != null) + if(entityListForCurrentObject != null + && !entityListForCurrentObject.contains(objectInGraph)) { - - if(!entityListForCurrentObject.contains(objectInGraph)) - { - entityListForCurrentObject.add(objectInGraph); - this.listsToStore.add(entityListForCurrentObject); - } + entityListForCurrentObject.add(objectInGraph); + this.listsToStore.add(entityListForCurrentObject); } } ).buildObjectGraphTraverser(); diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/transactions/EclipseStoreTransactionManager.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/transactions/EclipseStoreTransactionManager.java index 7e75b44f..44681088 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/transactions/EclipseStoreTransactionManager.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/transactions/EclipseStoreTransactionManager.java @@ -16,7 +16,6 @@ package software.xdev.spring.data.eclipse.store.transactions; import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; import org.springframework.transaction.support.AbstractPlatformTransactionManager; import org.springframework.transaction.support.DefaultTransactionStatus; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -28,7 +27,7 @@ public class EclipseStoreTransactionManager extends AbstractPlatformTransactionM private static final String TRANSACTION_MANAGER = "ATransactionManagerForThisThread"; @Override - protected Object doGetTransaction() throws TransactionException + protected Object doGetTransaction() { final EclipseStoreExistingTransactionObject transactionObject = (EclipseStoreExistingTransactionObject)TransactionSynchronizationManager.getResource(TRANSACTION_MANAGER); @@ -36,7 +35,7 @@ protected Object doGetTransaction() throws TransactionException } @Override - protected void doBegin(final Object transaction, final TransactionDefinition definition) throws TransactionException + protected void doBegin(final Object transaction, final TransactionDefinition definition) { final EclipseStoreExistingTransactionObject transactionObject = this.extractEclipseStoreTransaction(transaction); @@ -45,13 +44,13 @@ protected void doBegin(final Object transaction, final TransactionDefinition def } @Override - protected void doCommit(final DefaultTransactionStatus status) throws TransactionException + protected void doCommit(final DefaultTransactionStatus status) { this.extractEclipseStoreTransaction(status.getTransaction()).commitTransaction(); } @Override - protected void doRollback(final DefaultTransactionStatus status) throws TransactionException + protected void doRollback(final DefaultTransactionStatus status) { this.extractEclipseStoreTransaction(status.getTransaction()).rollbackTransaction(); } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java index a58bf983..fec963af 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java @@ -27,9 +27,11 @@ public LazyDaoObject(final Integer id, final Lazy value) super(id, value); } + @SuppressWarnings("PMD.UselessOverridingMethod") @Override public int hashCode() { + // TODO: Why is hashCode different than equals? return super.hashCode(); } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/TypesData.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/TypesData.java index 0062d6de..1f3b8c18 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/TypesData.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/TypesData.java @@ -53,6 +53,7 @@ import software.xdev.spring.data.eclipse.store.repository.lazy.SpringDataEclipseStoreLazy; +@SuppressWarnings("PMD.UseArrayListInsteadOfVector") // Vector is required for tests final class TypesData { private TypesData() From 3fcb13a1493be31ce57ea32f666379a7e4b5613c Mon Sep 17 00:00:00 2001 From: AB Date: Tue, 25 Jun 2024 16:38:35 +0200 Subject: [PATCH 32/49] Ignore auto generated classes --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 65a2c800..76093537 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,9 @@ .config/pmd/ruleset.xml + + **/benchmark/**/jmh_generated/** + From 8c68d3ebf2b098990f0a95e418c433a7a1af4043 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Wed, 26 Jun 2024 02:22:05 +0000 Subject: [PATCH 33/49] Update dependency @antora/cli to v3.1.8 --- docs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 86a7578d..e7d926ad 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,7 +3,7 @@ "@antora/lunr-extension": "^1.0.0-alpha.8" }, "devDependencies": { - "@antora/cli": "3.1.7", + "@antora/cli": "3.1.8", "@antora/site-generator": "3.1.7" } } \ No newline at end of file From 16dc7030ae24c35446207069a7d0ab35ba135082 Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Wed, 26 Jun 2024 02:22:08 +0000 Subject: [PATCH 34/49] Update dependency @antora/site-generator to v3.1.8 --- docs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index 86a7578d..1c677e70 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,6 +4,6 @@ }, "devDependencies": { "@antora/cli": "3.1.7", - "@antora/site-generator": "3.1.7" + "@antora/site-generator": "3.1.8" } } \ No newline at end of file From ebf6be83d05c84299ab63b2ff0bfabd48b8b4664 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 26 Jun 2024 06:38:51 +0200 Subject: [PATCH 35/49] Fix hashcode --- .../isolated/tests/special/types/LazyDaoObject.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java index fec963af..866ce53c 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java @@ -27,12 +27,19 @@ public LazyDaoObject(final Integer id, final Lazy value) super(id, value); } - @SuppressWarnings("PMD.UselessOverridingMethod") @Override public int hashCode() { - // TODO: Why is hashCode different than equals? - return super.hashCode(); + int result = 17; + if(this.getId() != null) + { + result = 31 * result + this.getId().hashCode(); + } + if(this.getValue() != null) + { + result = 31 * result + this.getValue().hashCode(); + } + return result; } @Override From 43440d888724d7eecd174a6943843cf22247a906 Mon Sep 17 00:00:00 2001 From: AB Date: Wed, 26 Jun 2024 07:54:22 +0200 Subject: [PATCH 36/49] Make equals hashcode niceer --- .../tests/special/types/LazyDaoObject.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java index 866ce53c..30c33150 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/special/types/LazyDaoObject.java @@ -16,8 +16,10 @@ package software.xdev.spring.data.eclipse.store.integration.isolated.tests.special.types; import java.util.Objects; +import java.util.Optional; import org.eclipse.serializer.reference.Lazy; +import org.eclipse.serializer.reference.Referencing; public class LazyDaoObject extends ComplexObject> @@ -30,16 +32,11 @@ public LazyDaoObject(final Integer id, final Lazy value) @Override public int hashCode() { - int result = 17; - if(this.getId() != null) - { - result = 31 * result + this.getId().hashCode(); - } - if(this.getValue() != null) - { - result = 31 * result + this.getValue().hashCode(); - } - return result; + return Objects.hash( + this.getId(), + Optional.ofNullable(this.getValue()) + .map(Referencing::get) + .orElse(null)); } @Override @@ -56,8 +53,6 @@ public boolean equals(final Object o) final ComplexObject> that = (ComplexObject>)o; return Objects.equals(this.getId(), that.getId()) && (this.getValue() == null && that.getValue() == null) - || Objects.equals( - this.getValue().get(), - that.getValue().get()); + || Objects.equals(this.getValue().get(), that.getValue().get()); } } From 3a5e87ab343b9aadba2bfcf20676c6fbdd5d8c06 Mon Sep 17 00:00:00 2001 From: AB Date: Wed, 26 Jun 2024 08:33:23 +0200 Subject: [PATCH 37/49] Compact ``createPredicateForStringMatcher`` --- .../query/criteria/CriteriaByExample.java | 103 +++++++----------- 1 file changed, 37 insertions(+), 66 deletions(-) diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java index 01479075..5e45f834 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/query/criteria/CriteriaByExample.java @@ -19,7 +19,9 @@ import java.util.Collection; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.function.BiPredicate; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -110,88 +112,57 @@ private Predicate createPredicateForSpecif return this.createPredicateForStringMatcher( specifier, setOrDefaultMatcher, - transformedExampledValue, - transformedValue); + transformedExampledValue.get(), + transformedValue.orElse(null)); }; } private boolean createPredicateForStringMatcher( final ExampleMatcher.PropertySpecifier specifier, final ExampleMatcher.StringMatcher setOrDefaultMatcher, - final Optional transformedExampledValue, - final Optional transformedValue) + final Object transformedExampledValue, // Never null + final Object transformedValue) // Nullable { - switch(setOrDefaultMatcher) + // Check exact matches + if(ExampleMatcher.StringMatcher.DEFAULT.equals(setOrDefaultMatcher) + || ExampleMatcher.StringMatcher.EXACT.equals(setOrDefaultMatcher)) { - case DEFAULT, EXACT -> + if(transformedExampledValue instanceof String) { - if(transformedExampledValue.get() instanceof String) - { - return this.valueToString(transformedValue, specifier).equals(this.valueToString( - transformedExampledValue, - specifier)); - } - return transformedExampledValue.equals(transformedValue); - } - case STARTING -> - { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return valueAsString.get() - .startsWith(this.valueToString(transformedExampledValue, specifier).get()); - } - case ENDING -> - { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return valueAsString.get().endsWith(this.valueToString(transformedExampledValue, specifier).get()); - } - case CONTAINING -> - { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return valueAsString.get().contains(this.valueToString(transformedExampledValue, specifier).get()); - } - case REGEX -> - { - final Optional valueAsString = this.valueToString(transformedValue, specifier); - if(valueAsString.isEmpty()) - { - return false; - } - return Pattern.compile( - this.valueToString(transformedExampledValue, specifier).get() - ) - .matcher(valueAsString.get()).find(); - } - default -> - { - return false; + return Objects.equals( + this.valueToString(transformedExampledValue, specifier), + this.valueToString(transformedValue, specifier)); } + return Objects.equals(transformedExampledValue, transformedValue); } + + // Check comparisons + final BiPredicate compareFunc = switch(setOrDefaultMatcher) + { + case STARTING -> String::startsWith; + case ENDING -> String::endsWith; + case CONTAINING -> String::contains; + case REGEX -> (v, example) -> Pattern.compile(example).matcher(v).find(); + default -> null; + }; + + return compareFunc != null + && Optional.ofNullable(this.valueToString(transformedValue, specifier)) + .map(v -> compareFunc.test(v, this.valueToString(transformedExampledValue, specifier))) + .orElse(false); } - private Optional valueToString( - final Optional value, + private String valueToString( + final Object value, final ExampleMatcher.PropertySpecifier specifier) { - if(value.isEmpty()) - { - return Optional.empty(); - } - if(specifier != null && Boolean.TRUE.equals(specifier.getIgnoreCase())) + if(value == null) { - return Optional.of(value.get().toString().toLowerCase(Locale.ROOT)); + return null; } - return Optional.of(value.get().toString()); + + return (specifier != null && Boolean.TRUE.equals(specifier.getIgnoreCase())) + ? value.toString().toLowerCase(Locale.ROOT) + : value.toString(); } } From c5d095c4c687a7d522de91ac3c4b427cefbd1892 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 26 Jun 2024 09:02:20 +0200 Subject: [PATCH 38/49] Refactored ID tests to be isolated --- .../store/integration/TestConfiguration.java | 2 +- .../tests => isolated/tests/id}/IdTest.java | 51 +++++++++++-------- .../tests/id/IdTestConfiguration.java | 38 ++++++++++++++ .../tests/id/model}/CustomerWithIdInt.java | 2 +- .../model}/CustomerWithIdIntRepository.java | 2 +- .../id/model}/CustomerWithIdInteger.java | 2 +- .../CustomerWithIdIntegerNoAutoGenerate.java | 2 +- ...WithIdIntegerNoAutoGenerateRepository.java | 2 +- .../CustomerWithIdIntegerRepository.java | 2 +- .../tests/id/model}/CustomerWithIdLong.java | 2 +- .../model}/CustomerWithIdLongRepository.java | 2 +- .../tests/id/model}/CustomerWithIdString.java | 2 +- .../CustomerWithIdStringRepository.java | 2 +- .../tests/id/model}/CustomerWithPurchase.java | 2 +- .../CustomerWithPurchaseRepository.java | 2 +- .../tests/id/model}/Purchase.java | 2 +- 16 files changed, 82 insertions(+), 35 deletions(-) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/tests => isolated/tests/id}/IdTest.java (88%) create mode 100644 spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdInt.java (96%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdIntRepository.java (90%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdInteger.java (96%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdIntegerNoAutoGenerate.java (96%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdIntegerNoAutoGenerateRepository.java (90%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdIntegerRepository.java (90%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdLong.java (95%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdLongRepository.java (90%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdString.java (95%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithIdStringRepository.java (90%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithPurchase.java (96%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/CustomerWithPurchaseRepository.java (90%) rename spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/{shared/repositories/id => isolated/tests/id/model}/Purchase.java (94%) diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/TestConfiguration.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/TestConfiguration.java index 924aa41e..08974a22 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/TestConfiguration.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/TestConfiguration.java @@ -55,7 +55,7 @@ public EmbeddedStorageFoundation createEmbeddedStorageFoundation() } @EventListener - public void handleContextRefresh(final ContextRefreshedEvent event) + public void handleContextRefresh(final ContextRefreshedEvent event) throws IOException { // Init with empty root object this.getStorageInstance().clearData(); diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/IdTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java similarity index 88% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/IdTest.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java index cf6f91b9..c28029a0 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/IdTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.tests; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id; import static software.xdev.spring.data.eclipse.store.helper.TestUtil.restartDatastore; @@ -23,33 +23,39 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; import software.xdev.spring.data.eclipse.store.helper.TestData; import software.xdev.spring.data.eclipse.store.helper.TestUtil; -import software.xdev.spring.data.eclipse.store.integration.shared.DefaultTestAnnotations; -import software.xdev.spring.data.eclipse.store.integration.shared.SharedTestConfiguration; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdInt; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdIntRepository; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdInteger; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdIntegerNoAutoGenerate; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdIntegerNoAutoGenerateRepository; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdIntegerRepository; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdLong; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdLongRepository; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdString; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithIdStringRepository; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithPurchase; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.CustomerWithPurchaseRepository; -import software.xdev.spring.data.eclipse.store.integration.shared.repositories.id.Purchase; +import software.xdev.spring.data.eclipse.store.integration.isolated.IsolatedTestAnnotations; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdInt; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdIntRepository; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdInteger; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdIntegerNoAutoGenerate; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdIntegerNoAutoGenerateRepository; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdIntegerRepository; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdLong; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdLongRepository; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdString; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithIdStringRepository; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithPurchase; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.CustomerWithPurchaseRepository; +import software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model.Purchase; import software.xdev.spring.data.eclipse.store.repository.EclipseStoreStorage; @SuppressWarnings("OptionalGetWithoutIsPresent") -@DefaultTestAnnotations +@IsolatedTestAnnotations +@ContextConfiguration(classes = {IdTestConfiguration.class}) class IdTest { + private final IdTestConfiguration configuration; + @Autowired - private SharedTestConfiguration configuration; + public IdTest(final IdTestConfiguration configuration) + { + this.configuration = configuration; + } @Test void testCreateSingleWithAutoIdInteger(@Autowired final CustomerWithIdIntegerRepository customerRepository) @@ -90,7 +96,8 @@ void testSaveSingleWithoutAnyPreviousCall(@Autowired final CustomerWithIdInteger @Test void testCreateSingleWithAutoIdIntegerWorkingCopyIdSet( - @Autowired final CustomerWithIdIntegerRepository customerRepository) + @Autowired final CustomerWithIdIntegerRepository customerRepository + ) { final CustomerWithIdInteger customer1 = new CustomerWithIdInteger(TestData.FIRST_NAME, TestData.LAST_NAME); Assertions.assertNull(customer1.getId()); @@ -120,7 +127,8 @@ void testCreateMultipleWithAutoIdInteger(@Autowired final CustomerWithIdIntegerR @Test void testCreateMultipleWithAutoIdIntegerSingleFinds( - @Autowired final CustomerWithIdIntegerRepository customerRepository) + @Autowired final CustomerWithIdIntegerRepository customerRepository + ) { final CustomerWithIdInteger customer1 = new CustomerWithIdInteger(TestData.FIRST_NAME, TestData.LAST_NAME); customerRepository.save(customer1); @@ -274,7 +282,8 @@ void testCreateMultipleWithNoAutoIdInteger( @Test void testSaveSingleWithAutoIdInteger( - @Autowired final CustomerWithIdIntegerRepository customerRepository) + @Autowired final CustomerWithIdIntegerRepository customerRepository + ) { final CustomerWithIdInteger customer1 = new CustomerWithIdInteger(); diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java new file mode 100644 index 00000000..0743859f --- /dev/null +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * 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 software.xdev.spring.data.eclipse.store.integration.isolated.tests.id; + +import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; +import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import software.xdev.spring.data.eclipse.store.integration.TestConfiguration; +import software.xdev.spring.data.eclipse.store.repository.config.EnableEclipseStoreRepositories; + + +@Configuration +@EnableEclipseStoreRepositories +public class IdTestConfiguration extends TestConfiguration +{ + @Autowired + protected IdTestConfiguration( + final EclipseStoreProperties defaultEclipseStoreProperties, + final EmbeddedStorageFoundationFactory defaultEclipseStoreProvider) + { + super(defaultEclipseStoreProperties, defaultEclipseStoreProvider); + } +} diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdInt.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInt.java similarity index 96% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdInt.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInt.java index 30a8c9ca..944d4bbe 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdInt.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInt.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.List; import java.util.Objects; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntRepository.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntRepository.java similarity index 90% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntRepository.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntRepository.java index 8e32578d..27958635 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntRepository.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntRepository.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import org.springframework.data.repository.CrudRepository; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdInteger.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java similarity index 96% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdInteger.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java index 81cd2f1f..7a26977e 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdInteger.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.List; import java.util.Objects; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerNoAutoGenerate.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerNoAutoGenerate.java similarity index 96% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerNoAutoGenerate.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerNoAutoGenerate.java index c3540763..9ac26318 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerNoAutoGenerate.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerNoAutoGenerate.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.List; import java.util.Objects; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerNoAutoGenerateRepository.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerNoAutoGenerateRepository.java similarity index 90% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerNoAutoGenerateRepository.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerNoAutoGenerateRepository.java index 55c15fe0..8aff5e66 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerNoAutoGenerateRepository.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerNoAutoGenerateRepository.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import org.springframework.data.repository.CrudRepository; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerRepository.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerRepository.java similarity index 90% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerRepository.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerRepository.java index 8846c83a..6fc66730 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdIntegerRepository.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdIntegerRepository.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import org.springframework.data.repository.CrudRepository; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdLong.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdLong.java similarity index 95% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdLong.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdLong.java index 1fa239b0..7f5cc104 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdLong.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdLong.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.Objects; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdLongRepository.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdLongRepository.java similarity index 90% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdLongRepository.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdLongRepository.java index d70b9b76..0646719b 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdLongRepository.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdLongRepository.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import org.springframework.data.repository.CrudRepository; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdString.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdString.java similarity index 95% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdString.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdString.java index 4ff3e317..930015d9 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdString.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdString.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.Objects; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdStringRepository.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdStringRepository.java similarity index 90% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdStringRepository.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdStringRepository.java index 7efb2535..4721e8a0 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithIdStringRepository.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdStringRepository.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import org.springframework.data.repository.CrudRepository; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithPurchase.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithPurchase.java similarity index 96% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithPurchase.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithPurchase.java index d55f7503..2f34bf34 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithPurchase.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithPurchase.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.ArrayList; import java.util.List; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithPurchaseRepository.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithPurchaseRepository.java similarity index 90% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithPurchaseRepository.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithPurchaseRepository.java index 9bc5eae8..cdbc1b30 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/CustomerWithPurchaseRepository.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithPurchaseRepository.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import org.springframework.data.repository.CrudRepository; diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/Purchase.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/Purchase.java similarity index 94% rename from spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/Purchase.java rename to spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/Purchase.java index 2a3af61e..a96367b6 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/repositories/id/Purchase.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/Purchase.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.spring.data.eclipse.store.integration.shared.repositories.id; +package software.xdev.spring.data.eclipse.store.integration.isolated.tests.id.model; import java.util.Objects; From 27af3676260e9bcbe437bc1002f80d00ff0b1b60 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 26 Jun 2024 09:27:55 +0200 Subject: [PATCH 39/49] Implemented Tests for ID Replacement behavior --- .../integration/isolated/tests/id/IdTest.java | 97 +++++++++++++++++++ .../tests/id/model/CustomerWithIdInteger.java | 7 ++ 2 files changed, 104 insertions(+) diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java index c28029a0..03f7b67f 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java @@ -421,4 +421,101 @@ void testAutoIdWithTwoSameSubnodesWithSameIdSameNode( } ); } + + @Test + void testReplaceWithId(@Autowired final CustomerWithIdIntegerNoAutoGenerateRepository customerRepository) + { + final CustomerWithIdIntegerNoAutoGenerate existingCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME, TestData.LAST_NAME); + customerRepository.save(existingCustomer); + + final CustomerWithIdIntegerNoAutoGenerate newCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME_ALTERNATIVE, + TestData.LAST_NAME_ALTERNATIVE); + customerRepository.save(newCustomer); + + TestUtil.doBeforeAndAfterRestartOfDatastore( + this.configuration, + () -> { + final List loadedCustomer = + TestUtil.iterableToList(customerRepository.findAll()); + + Assertions.assertEquals(1, loadedCustomer.size()); + Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName()); + Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName()); + } + ); + } + + @Test + void testReplaceWithAutoId(@Autowired final CustomerWithIdIntegerRepository customerRepository) + { + final CustomerWithIdInteger existingCustomer = + new CustomerWithIdInteger(TestData.FIRST_NAME, TestData.LAST_NAME); + customerRepository.save(existingCustomer); + final Integer existingId = customerRepository.findAll().iterator().next().getId(); + + final CustomerWithIdInteger newCustomer = new CustomerWithIdInteger(existingId, + TestData.FIRST_NAME_ALTERNATIVE, + TestData.LAST_NAME_ALTERNATIVE); + customerRepository.save(newCustomer); + + TestUtil.doBeforeAndAfterRestartOfDatastore( + this.configuration, + () -> { + final List loadedCustomer = + TestUtil.iterableToList(customerRepository.findAll()); + + Assertions.assertEquals(1, loadedCustomer.size()); + Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName()); + Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName()); + } + ); + } + + @Test + void testReplaceWithIdSaveAll(@Autowired final CustomerWithIdIntegerNoAutoGenerateRepository customerRepository) + { + final CustomerWithIdIntegerNoAutoGenerate existingCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME, TestData.LAST_NAME); + final CustomerWithIdIntegerNoAutoGenerate newCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME_ALTERNATIVE, + TestData.LAST_NAME_ALTERNATIVE); + customerRepository.saveAll(List.of(existingCustomer, newCustomer)); + + TestUtil.doBeforeAndAfterRestartOfDatastore( + this.configuration, + () -> { + final List loadedCustomer = + TestUtil.iterableToList(customerRepository.findAll()); + + Assertions.assertEquals(1, loadedCustomer.size()); + Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName()); + Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName()); + } + ); + } + + @Test + void testAddTwoWithId(@Autowired final CustomerWithIdIntegerNoAutoGenerateRepository customerRepository) + { + final CustomerWithIdIntegerNoAutoGenerate existingCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME, TestData.LAST_NAME); + customerRepository.save(existingCustomer); + + final CustomerWithIdIntegerNoAutoGenerate newCustomer = + new CustomerWithIdIntegerNoAutoGenerate(2, TestData.FIRST_NAME_ALTERNATIVE, + TestData.LAST_NAME_ALTERNATIVE); + customerRepository.save(newCustomer); + + TestUtil.doBeforeAndAfterRestartOfDatastore( + this.configuration, + () -> { + final List loadedCustomer = + TestUtil.iterableToList(customerRepository.findAll()); + + Assertions.assertEquals(2, loadedCustomer.size()); + } + ); + } } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java index 7a26977e..a9d98356 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/model/CustomerWithIdInteger.java @@ -42,6 +42,13 @@ public CustomerWithIdInteger(final String firstName, final String lastName) this.lastName = lastName; } + public CustomerWithIdInteger(final Integer id, final String firstName, final String lastName) + { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + public String getFirstName() { return this.firstName; From 7c6869ea1f9c46a7f58bc989f03a230d9e383770 Mon Sep 17 00:00:00 2001 From: AB Date: Wed, 26 Jun 2024 10:12:18 +0200 Subject: [PATCH 40/49] Fix CPD --- pom.xml | 3 + ...bstractStoringSimpleCustomerBenchmark.java | 50 +++++++++ ...ingAndChangingSimpleCustomerBenchmark.java | 45 +------- .../StoringSimpleCustomerBenchmark.java | 44 +------- .../isolated/tests/lazy/LazyTest.java | 76 +++++-------- .../TransactionsConcurrencyTest.java | 64 ++++------- .../tests/transactions/TransactionsTest.java | 19 +--- .../shared/tests/ChangeRootTests.java | 43 +++----- .../shared/tests/RealLifeTests.java | 102 +++++++----------- .../shared/tests/WorkingCopyTests.java | 69 ++---------- 10 files changed, 174 insertions(+), 341 deletions(-) create mode 100644 spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/AbstractStoringSimpleCustomerBenchmark.java diff --git a/pom.xml b/pom.xml index 76093537..c3d84890 100644 --- a/pom.xml +++ b/pom.xml @@ -84,6 +84,9 @@ **/benchmark/**/jmh_generated/** + + **/shared/**/Customer* + **/shared/**/Child* diff --git a/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/AbstractStoringSimpleCustomerBenchmark.java b/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/AbstractStoringSimpleCustomerBenchmark.java new file mode 100644 index 00000000..0931bd64 --- /dev/null +++ b/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/AbstractStoringSimpleCustomerBenchmark.java @@ -0,0 +1,50 @@ +package software.xdev.spring.data.eclipse.store.benchmark.benchmarks.simple.customer; + +import org.openjdk.jmh.annotations.Benchmark; + +import software.xdev.spring.data.eclipse.store.benchmark.SpringState; + + +@SuppressWarnings("checkstyle:MagicNumber") +public abstract class AbstractStoringSimpleCustomerBenchmark +{ + protected abstract void saveCustomerInForEach(final SpringState state, final int entityCount); + + protected abstract void saveCustomerInSaveAll(final SpringState state, final int entityCount); + + @Benchmark + public void save100CustomerInForEach(final SpringState state) + { + this.saveCustomerInForEach(state, 100); + } + + @Benchmark + public void save1000CustomerInForEach(final SpringState state) + { + this.saveCustomerInForEach(state, 1_000); + } + + @Benchmark + public void save100CustomerInSaveAll(final SpringState state) + { + this.saveCustomerInSaveAll(state, 100); + } + + @Benchmark + public void save1000CustomerInSaveAll(final SpringState state) + { + this.saveCustomerInSaveAll(state, 1_000); + } + + @Benchmark + public void save10000CustomerInSaveAll(final SpringState state) + { + this.saveCustomerInSaveAll(state, 10_000); + } + + @Benchmark + public void save100000CustomerInSaveAll(final SpringState state) + { + this.saveCustomerInSaveAll(state, 100_000); + } +} diff --git a/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringAndChangingSimpleCustomerBenchmark.java b/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringAndChangingSimpleCustomerBenchmark.java index aea67d84..83f63914 100644 --- a/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringAndChangingSimpleCustomerBenchmark.java +++ b/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringAndChangingSimpleCustomerBenchmark.java @@ -8,8 +8,7 @@ import software.xdev.spring.data.eclipse.store.repository.config.EclipseStoreClientConfiguration; -@SuppressWarnings("checkstyle:MagicNumber") -public class StoringAndChangingSimpleCustomerBenchmark +public class StoringAndChangingSimpleCustomerBenchmark extends AbstractStoringSimpleCustomerBenchmark { @Benchmark public void saveSingleCustomer(final SpringState state) @@ -29,43 +28,8 @@ public void saveSingleCustomer(final SpringState state) }); } - @Benchmark - public void save100CustomerInForEach(final SpringState state) - { - this.saveCustomerInForEach(state, 100); - } - - @Benchmark - public void save100CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 100); - } - - @Benchmark - public void save1000CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 1_000); - } - - @Benchmark - public void save10000CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 10_000); - } - - @Benchmark - public void save1000CustomerInForEach(final SpringState state) - { - this.saveCustomerInForEach(state, 1_000); - } - - @Benchmark - public void save100000CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 100_000); - } - - private void saveCustomerInForEach(final SpringState state, final int entityCount) + @Override + protected void saveCustomerInForEach(final SpringState state, final int entityCount) { final CustomerRepository customerRepository1 = state.getBean(CustomerRepository.class); IntStream.range(0, entityCount).forEach( @@ -84,7 +48,8 @@ private void saveCustomerInForEach(final SpringState state, final int entityCoun }); } - private void saveCustomerInSaveAll(final SpringState state, final int entityCount) + @Override + protected void saveCustomerInSaveAll(final SpringState state, final int entityCount) { final CustomerRepository customerRepository = state.getBean(CustomerRepository.class); customerRepository.saveAll( diff --git a/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringSimpleCustomerBenchmark.java b/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringSimpleCustomerBenchmark.java index cd14c20f..bf86ccae 100644 --- a/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringSimpleCustomerBenchmark.java +++ b/spring-data-eclipse-store-benchmark/src/main/java/software/xdev/spring/data/eclipse/store/benchmark/benchmarks/simple/customer/StoringSimpleCustomerBenchmark.java @@ -8,7 +8,7 @@ @SuppressWarnings("checkstyle:MagicNumber") -public class StoringSimpleCustomerBenchmark +public class StoringSimpleCustomerBenchmark extends AbstractStoringSimpleCustomerBenchmark { @Benchmark public void saveSingleCustomer(final SpringState state) @@ -17,36 +17,6 @@ public void saveSingleCustomer(final SpringState state) customerRepository.save(new Customer("Test", "Test")); } - @Benchmark - public void save100CustomerInForEach(final SpringState state) - { - this.saveCustomerInForEach(state, 100); - } - - @Benchmark - public void save100CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 100); - } - - @Benchmark - public void save1000CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 1_000); - } - - @Benchmark - public void save10000CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 10_000); - } - - @Benchmark - public void save1000CustomerInForEach(final SpringState state) - { - this.saveCustomerInForEach(state, 1_000); - } - @Benchmark public void save10000CustomerInForEach(final SpringState state) { @@ -59,13 +29,8 @@ public void save10000CustomerInForEachParallel(final SpringState state) this.saveCustomerInForEachParallel(state, 10_000); } - @Benchmark - public void save100000CustomerInSaveAll(final SpringState state) - { - this.saveCustomerInSaveAll(state, 100_000); - } - - private void saveCustomerInForEach(final SpringState state, final int entityCount) + @Override + protected void saveCustomerInForEach(final SpringState state, final int entityCount) { final CustomerRepository customerRepository = state.getBean(CustomerRepository.class); IntStream.range(0, entityCount).forEach( @@ -81,7 +46,8 @@ private void saveCustomerInForEachParallel(final SpringState state, final int en ); } - private void saveCustomerInSaveAll(final SpringState state, final int entityCount) + @Override + protected void saveCustomerInSaveAll(final SpringState state, final int entityCount) { final CustomerRepository customerRepository = state.getBean(CustomerRepository.class); customerRepository.saveAll( diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/lazy/LazyTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/lazy/LazyTest.java index 68c3b613..f2b4d490 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/lazy/LazyTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/lazy/LazyTest.java @@ -188,16 +188,8 @@ void lazyWorkingCopyChangeAfterRestart(@Autowired final ObjectWithLazyRepository @Test void lazyStoreComplexObject(@Autowired final ObjectWithLazyRepository repository) { - final ObjectWithLazy newLazy = new ObjectWithLazy<>(); - final ComplexLazyObject objectToStore = new ComplexLazyObject( - SpringDataEclipseStoreLazy.build(new SimpleObject(TestData.DUMMY_STRING)), - new ArrayList<>(Arrays.asList( - SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING))), - SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING_ALTERNATIVE))) - )) - ); - newLazy.setLazy(SpringDataEclipseStoreLazy.build(objectToStore)); - repository.save(newLazy); + final ComplexLazyObject objectToStore = + prepareLazyComplexObject(repository); TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, @@ -222,16 +214,7 @@ void lazyStoreComplexObject(@Autowired final ObjectWithLazyRepository repository) { - final ObjectWithLazy newLazy = new ObjectWithLazy<>(); - final ComplexLazyObject objectToStore = new ComplexLazyObject( - SpringDataEclipseStoreLazy.build(new SimpleObject(TestData.DUMMY_STRING)), - new ArrayList<>(Arrays.asList( - SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING))), - SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING_ALTERNATIVE))) - )) - ); - newLazy.setLazy(SpringDataEclipseStoreLazy.build(objectToStore)); - repository.save(newLazy); + prepareLazyComplexObject(repository); restartDatastore(this.configuration); @@ -243,50 +226,43 @@ void lazyChangeComplexObject(@Autowired final ObjectWithLazyRepository { - final ObjectWithLazy loadedObject = repository.findAll().get(0); - Assertions.assertNotSame(loadedObjectToChange, loadedObject); - Assertions.assertNotSame( - loadedObjectToChange.getLazy().get(), - loadedObject.getLazy().get() - ); - Assertions.assertEquals( - loadedObjectToChange.getLazy().get().getListOfLazyListOfString().size(), - loadedObject.getLazy().get().getListOfLazyListOfString().size() - ); - Assertions.assertEquals( - loadedObjectToChange.getLazy().get().getListOfLazyListOfString().get(0).get().size(), - loadedObject.getLazy().get().getListOfLazyListOfString().get(0).get().size() - ); - Assertions.assertEquals( - loadedObjectToChange.getLazy().get().getListOfLazyListOfString().get(0).get().get(0), - loadedObject.getLazy().get().getListOfLazyListOfString().get(0).get().get(0) - ); - } - ); + this.validateLazyComplexObject(repository, loadedObjectToChange); } @Test void lazyReloadAndRestoreComplexObject(@Autowired final ObjectWithLazyRepository repository) + { + prepareLazyComplexObject(repository); + + restartDatastore(this.configuration); + + final ObjectWithLazy loadedObjectToChange = repository.findAll().get(0); + repository.save(loadedObjectToChange); + + this.validateLazyComplexObject(repository, loadedObjectToChange); + } + + private static ComplexLazyObject prepareLazyComplexObject( + final ObjectWithLazyRepository repository) { final ObjectWithLazy newLazy = new ObjectWithLazy<>(); final ComplexLazyObject objectToStore = new ComplexLazyObject( SpringDataEclipseStoreLazy.build(new SimpleObject(TestData.DUMMY_STRING)), new ArrayList<>(Arrays.asList( - SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING))), - SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING_ALTERNATIVE))) + SpringDataEclipseStoreLazy.build(new ArrayList<>(List.of(TestData.DUMMY_STRING))), + SpringDataEclipseStoreLazy.build(new ArrayList<>(List.of(TestData.DUMMY_STRING_ALTERNATIVE))) )) ); newLazy.setLazy(SpringDataEclipseStoreLazy.build(objectToStore)); repository.save(newLazy); - restartDatastore(this.configuration); - - final ObjectWithLazy loadedObjectToChange = repository.findAll().get(0); - repository.save(loadedObjectToChange); - + return objectToStore; + } + + private void validateLazyComplexObject( + final ObjectWithLazyRepository repository, + final ObjectWithLazy loadedObjectToChange) + { TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, () -> { diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsConcurrencyTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsConcurrencyTest.java index d49ad14d..70d3b7b0 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsConcurrencyTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsConcurrencyTest.java @@ -28,6 +28,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.PlatformTransactionManager; @@ -49,51 +51,18 @@ public TransactionsConcurrencyTest(final AccountRepository accountRepository) this.accountRepository = accountRepository; } - @Test - void testSaveConcurrentlyPreviouslyNonExistingAccounts( - @Autowired final PlatformTransactionManager transactionManager - ) - throws InterruptedException - { - final List testAccounts = - IntStream.range(1, 1000).mapToObj((i) -> new Account(i, BigDecimal.TEN)).toList(); - - final ExecutorService service = Executors.newFixedThreadPool(10); - final CountDownLatch latch = new CountDownLatch(testAccounts.size()); - testAccounts.forEach( - account -> - service.execute(() -> - { - new TransactionTemplate(transactionManager).execute( - status -> - { - account.setBalance(account.getBalance().subtract(BigDecimal.ONE)); - this.accountRepository.save(account); - return null; - }); - Assertions.assertEquals( - BigDecimal.valueOf(9), - this.accountRepository.findById(account.getId()).get().getBalance()); - latch.countDown(); - } - ) - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - - final List accounts = TestUtil.iterableToList(this.accountRepository.findAll()); - assertEquals(testAccounts.size(), accounts.size()); - accounts.forEach(account -> Assertions.assertEquals(BigDecimal.valueOf(9), account.getBalance())); - } - - @Test - void testSaveConcurrentlyPreviouslyExistingAccounts( - @Autowired final PlatformTransactionManager transactionManager) - throws InterruptedException + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void saveConcurrently( + final boolean previouslyExisting, + @Autowired final PlatformTransactionManager transactionManager) throws InterruptedException { final List testAccounts = - IntStream.range(1, 100).mapToObj((i) -> new Account(i, BigDecimal.TEN)).toList(); - this.accountRepository.saveAll(testAccounts); + IntStream.range(1, 1000).mapToObj(i -> new Account(i, BigDecimal.TEN)).toList(); + if(previouslyExisting) + { + this.accountRepository.saveAll(testAccounts); + } final ExecutorService service = Executors.newFixedThreadPool(10); final CountDownLatch latch = new CountDownLatch(testAccounts.size()); @@ -101,9 +70,12 @@ void testSaveConcurrentlyPreviouslyExistingAccounts( account -> service.execute(() -> { - Assertions.assertEquals( - BigDecimal.TEN, - this.accountRepository.findById(account.getId()).get().getBalance()); + if(previouslyExisting) + { + Assertions.assertEquals( + BigDecimal.TEN, + this.accountRepository.findById(account.getId()).get().getBalance()); + } new TransactionTemplate(transactionManager).execute( status -> { diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java index 8756e472..07b34579 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java @@ -113,24 +113,7 @@ void accountTransactionChangeAfterSave(@Autowired final PlatformTransactionManag @Test void accountAndCounterTransactionSequential(@Autowired final PlatformTransactionManager transactionManager) { - new TransactionTemplate(transactionManager).execute( - status -> - { - this.account1.setBalance(this.account1.getBalance().subtract(BigDecimal.ONE)); - this.accountRepository.save(this.account1); - - this.account2.setBalance(this.account2.getBalance().add(BigDecimal.ONE)); - this.accountRepository.save(this.account2); - return null; - } - ); - - Assertions.assertEquals( - BigDecimal.valueOf(9), - this.accountRepository.findById(this.account1.getId()).get().getBalance()); - Assertions.assertEquals( - BigDecimal.ONE, - this.accountRepository.findById(this.account2.getId()).get().getBalance()); + this.accountTransactionWorking(transactionManager); new TransactionTemplate(transactionManager).execute( status -> diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/ChangeRootTests.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/ChangeRootTests.java index 356f6c1a..e229eaa0 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/ChangeRootTests.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/ChangeRootTests.java @@ -29,7 +29,7 @@ @DefaultTestAnnotations -public class ChangeRootTests +class ChangeRootTests { public static final String CHILD_1 = "child1"; public static final String CHILD_2 = "child2"; @@ -37,9 +37,9 @@ public class ChangeRootTests public static final String PARENT_2 = "parent2"; @Autowired - private NodeRepository repository; + NodeRepository repository; @Autowired - private SharedTestConfiguration configuration; + SharedTestConfiguration configuration; //@formatter:off /** @@ -54,16 +54,7 @@ void testSaveParentAndFindAll() final Node parentNode = new Node(PARENT_1, List.of(childNode1, childNode2)); this.repository.save(parentNode); - TestUtil.doBeforeAndAfterRestartOfDatastore( - this.configuration, - () -> { - final List nodes = TestUtil.iterableToList(this.repository.findAll()); - Assertions.assertEquals(3, nodes.size()); - Assertions.assertTrue(Node.getNodeWithName(nodes, PARENT_1).isPresent()); - Assertions.assertTrue(Node.getNodeWithName(nodes, CHILD_1).isPresent()); - Assertions.assertTrue(Node.getNodeWithName(nodes, CHILD_2).isPresent()); - } - ); + this.validate(PARENT_1, CHILD_1, CHILD_2); } //@formatter:off @@ -81,16 +72,7 @@ void testSaveRecursive() childNode1.getChildren().add(parentNode2); this.repository.save(parentNode1); - TestUtil.doBeforeAndAfterRestartOfDatastore( - this.configuration, - () -> { - final List nodes = TestUtil.iterableToList(this.repository.findAll()); - Assertions.assertEquals(3, nodes.size()); - Assertions.assertTrue(Node.getNodeWithName(nodes, PARENT_1).isPresent()); - Assertions.assertTrue(Node.getNodeWithName(nodes, CHILD_1).isPresent()); - Assertions.assertTrue(Node.getNodeWithName(nodes, PARENT_2).isPresent()); - } - ); + this.validate(PARENT_1, CHILD_1, PARENT_2); } //@formatter:off @@ -109,14 +91,21 @@ void testSaveGraph() childNode2.getChildren().add(parentNode); this.repository.save(parentNode); + this.validate(PARENT_1, CHILD_1, CHILD_2); + } + + private void validate(final String... presentNodes) + { TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, () -> { final List nodes = TestUtil.iterableToList(this.repository.findAll()); - Assertions.assertEquals(3, nodes.size()); - Assertions.assertTrue(Node.getNodeWithName(nodes, PARENT_1).isPresent()); - Assertions.assertTrue(Node.getNodeWithName(nodes, CHILD_1).isPresent()); - Assertions.assertTrue(Node.getNodeWithName(nodes, CHILD_2).isPresent()); + Assertions.assertEquals(presentNodes.length, nodes.size()); + + for(final String expectedNodeName : presentNodes) + { + Assertions.assertTrue(Node.getNodeWithName(nodes, expectedNodeName).isPresent()); + } } ); } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/RealLifeTests.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/RealLifeTests.java index 026a3a05..2dd2c883 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/RealLifeTests.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/RealLifeTests.java @@ -40,15 +40,18 @@ @SuppressWarnings("OptionalGetWithoutIsPresent") @DefaultTestAnnotations -public class RealLifeTests +class RealLifeTests { - public static final String STATIONERY = "Stationery"; - public static final String BUILDING_MATERIAL = "Building Material"; - public static final String PEN = "Pen"; - public static final String BRICK = "Brick"; - public static final int PEN_AMOUNT = 5; - public static final int BRICK_AMOUNT = 2; - public static final String WAREHOUSE_WEIDEN = "Weiden"; + static final String STATIONERY = "Stationery"; + static final String BUILDING_MATERIAL = "Building Material"; + static final String PEN = "Pen"; + static final String BRICK = "Brick"; + static final int PEN_AMOUNT = 5; + static final int BRICK_AMOUNT = 2; + static final String WAREHOUSE_WEIDEN = "Weiden"; + static final String SHOE_ARTICLE_NAME = "Shoe"; + static final String SHOES_ARTICLE_GROUP = "Shoes"; + @Autowired InvoiceRepository invoiceRepository; @Autowired @@ -108,33 +111,19 @@ void testReplacePositionWithExistingArticle() @Test void testReplacePositionWithNewArticleThroughInvoiceRepository() { - final String shoeArticleName = "Shoe"; this.buildDefaultModelAndSaveIt(); final Invoice invoice = TestUtil.iterableToList(this.invoiceRepository.findAll()).get(0); final List positions = invoice.getPositions(); positions.remove(1); - final ArticleGroup shoesGroup = new ArticleGroup("Shoes"); - final Article shoe = - new Article(shoeArticleName, shoesGroup, positions.get(0).getArticle().getWarehouses().get(0)); - positions.add(new Position(shoe, 4)); + createAndAddShoeToPosition(positions); this.invoiceRepository.save(invoice); TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, () -> { final Invoice loadedInvoice = TestUtil.iterableToList(this.invoiceRepository.findAll()).get(0); - final Optional - positionOfShoe = getPositionWithArticleWithName(loadedInvoice.getPositions(), shoeArticleName); - final Optional positionWithAmount4 = - loadedInvoice.getPositions().stream().filter(position -> position.getAmount() == 4).findFirst(); - Assertions.assertEquals(2, loadedInvoice.getPositions().size()); - Assertions.assertTrue(positionWithAmount4.isPresent()); - Assertions.assertTrue(positionOfShoe.isPresent()); - Assertions.assertEquals("Shoes", positionOfShoe.get().getArticle().getGroup().getName()); - Assertions.assertSame( - loadedInvoice.getPositions().get(0).getArticle().getWarehouses().get(0), - loadedInvoice.getPositions().get(1).getArticle().getWarehouses().get(0)); + this.validatePositions(loadedInvoice.getPositions(), 2); } ); } @@ -142,32 +131,18 @@ void testReplacePositionWithNewArticleThroughInvoiceRepository() @Test void testAddNewArticleWithSameWarehouse() { - final String shoeArticleName = "Shoe"; this.buildDefaultModelAndSaveIt(); final Invoice invoice = TestUtil.iterableToList(this.invoiceRepository.findAll()).get(0); final List positions = invoice.getPositions(); - final ArticleGroup shoesGroup = new ArticleGroup("Shoes"); - final Article shoe = - new Article(shoeArticleName, shoesGroup, positions.get(0).getArticle().getWarehouses().get(0)); - positions.add(new Position(shoe, 4)); + createAndAddShoeToPosition(positions); this.invoiceRepository.save(invoice); TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, () -> { final Invoice loadedInvoice = TestUtil.iterableToList(this.invoiceRepository.findAll()).get(0); - final Optional - positionOfShoe = getPositionWithArticleWithName(loadedInvoice.getPositions(), shoeArticleName); - final Optional positionWithAmount4 = - loadedInvoice.getPositions().stream().filter(position -> position.getAmount() == 4).findFirst(); - Assertions.assertEquals(3, loadedInvoice.getPositions().size()); - Assertions.assertTrue(positionWithAmount4.isPresent()); - Assertions.assertTrue(positionOfShoe.isPresent()); - Assertions.assertEquals("Shoes", positionOfShoe.get().getArticle().getGroup().getName()); - Assertions.assertSame( - loadedInvoice.getPositions().get(0).getArticle().getWarehouses().get(0), - loadedInvoice.getPositions().get(1).getArticle().getWarehouses().get(0)); + this.validatePositions(loadedInvoice.getPositions(), 3); Assertions.assertSame( loadedInvoice.getPositions().get(1).getArticle().getWarehouses().get(0), loadedInvoice.getPositions().get(2).getArticle().getWarehouses().get(0)); @@ -178,48 +153,45 @@ void testAddNewArticleWithSameWarehouse() @Test void testReplacePositionWithNewArticleThroughPositionRepository() { - final String shoeArticleName = "Shoe"; this.buildDefaultModelAndSaveIt(); List positions = TestUtil.iterableToList(this.positionRepository.findAll()); this.positionRepository.delete(positions.get(1)); positions = TestUtil.iterableToList(this.positionRepository.findAll()); - final ArticleGroup shoesGroup = new ArticleGroup("Shoes"); - final Article shoe = - new Article(shoeArticleName, shoesGroup, positions.get(0).getArticle().getWarehouses().get(0)); - positions.add(new Position(shoe, 4)); + createAndAddShoeToPosition(positions); this.positionRepository.saveAll(positions); TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, () -> { final List loadedPositions = TestUtil.iterableToList(this.positionRepository.findAll()); - final Optional - positionOfShoe = getPositionWithArticleWithName(loadedPositions, shoeArticleName); - final Optional positionWithAmount4 = - loadedPositions.stream().filter(position -> position.getAmount() == 4).findFirst(); - Assertions.assertEquals(2, loadedPositions.size()); - Assertions.assertTrue(positionWithAmount4.isPresent()); - Assertions.assertTrue(positionOfShoe.isPresent()); - Assertions.assertEquals("Shoes", positionOfShoe.get().getArticle().getGroup().getName()); - Assertions.assertSame( - loadedPositions.get(0).getArticle().getWarehouses().get(0), - loadedPositions.get(1).getArticle().getWarehouses().get(0)); + this.validatePositions(loadedPositions, 2); } ); } + private void validatePositions(final List positions, final int expectedSize) + { + final Optional + positionOfShoe = getPositionWithArticleWithName(positions, SHOE_ARTICLE_NAME); + final Optional positionWithAmount4 = + positions.stream().filter(position -> position.getAmount() == 4).findFirst(); + Assertions.assertEquals(expectedSize, positions.size()); + Assertions.assertTrue(positionWithAmount4.isPresent()); + Assertions.assertTrue(positionOfShoe.isPresent()); + Assertions.assertEquals(SHOES_ARTICLE_GROUP, positionOfShoe.get().getArticle().getGroup().getName()); + Assertions.assertSame( + positions.get(0).getArticle().getWarehouses().get(0), + positions.get(1).getArticle().getWarehouses().get(0)); + } + @Test void testReplacePositionWithNewArticleAndUseImmutableList() { - final String shoeArticleName = "Shoe"; this.buildDefaultModelAndSaveIt(); final List positions = TestUtil.iterableToList(this.positionRepository.findAll()); - final ArticleGroup shoesGroup = new ArticleGroup("Shoes"); - final Article shoe = - new Article(shoeArticleName, shoesGroup, List.of(positions.get(0).getArticle().getWarehouses().get(0))); - positions.add(new Position(shoe, 4)); + createAndAddShoeToPosition(positions); this.positionRepository.saveAll(positions); TestUtil.doBeforeAndAfterRestartOfDatastore( @@ -233,6 +205,14 @@ void testReplacePositionWithNewArticleAndUseImmutableList() ); } + private static void createAndAddShoeToPosition(final List positions) + { + final ArticleGroup shoesGroup = new ArticleGroup(SHOES_ARTICLE_GROUP); + final Article shoe = + new Article(SHOE_ARTICLE_NAME, shoesGroup, List.of(positions.get(0).getArticle().getWarehouses().get(0))); + positions.add(new Position(shoe, 4)); + } + @Test void testSaveTwoObjectsWithSameReferenceThroughPositionRepository() { diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/WorkingCopyTests.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/WorkingCopyTests.java index 84de03cb..30edd01a 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/WorkingCopyTests.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/shared/tests/WorkingCopyTests.java @@ -20,6 +20,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import software.xdev.spring.data.eclipse.store.helper.TestData; @@ -96,12 +98,6 @@ void testBasicDoubleCopy() Assertions.assertNotSame(customers1.get(0), customers2.get(0)); } - //@formatter:off - /** - * □-□ - * □-┘ - **/ - //@formatter:on @Test void testStoreGraphWithCircularRelation() { @@ -136,53 +132,9 @@ void testStoreGraphWithCircularRelation() ); } - //@formatter:off - /** - * □-□ - * □-┘ - **/ - //@formatter:on - @Test - void testStoreGraphWithCircularRelationWithDoubleSave() - { - final Node childNode = new Node(CHILD_NAME_1); - final Node parentNode1 = new Node(PARENT_NAME_1, List.of(childNode)); - final Node parentNode2 = new Node(PARENT_NAME_2); - childNode.getChildren().add(parentNode2); - - this.nodeRepository.save(parentNode1); - this.nodeRepository.save(parentNode2); - - TestUtil.doBeforeAndAfterRestartOfDatastore( - this.configuration, - () -> { - final List loadedNodes = TestUtil.iterableToList(this.nodeRepository.findAll()); - Assertions.assertEquals(3, loadedNodes.size()); - - final Node loadedChildNode = - loadedNodes.stream().filter(node -> node.getName().equals(CHILD_NAME_1)).findFirst().get(); - Assertions.assertEquals(CHILD_NAME_1, loadedChildNode.getName()); - final Node loadedParentNode1 = - loadedNodes.stream().filter(node -> node.getName().equals(PARENT_NAME_1)).findFirst().get(); - Assertions.assertEquals(PARENT_NAME_1, loadedParentNode1.getName()); - final Node loadedParentNode2 = - loadedNodes.stream().filter(node -> node.getName().equals(PARENT_NAME_2)).findFirst().get(); - Assertions.assertEquals(PARENT_NAME_2, loadedParentNode2.getName()); - - Assertions.assertSame(loadedParentNode1.getChildren().get(0), loadedChildNode); - Assertions.assertSame(loadedChildNode.getChildren().get(0), loadedParentNode2); - } - ); - } - - //@formatter:off - /** - * □-□ - * □-┘ - **/ - //@formatter:on - @Test - void testStoreGraphWithCircularRelationWithTrippleSave() + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void storeGraphWithCircularRelationWithMultiSave(final boolean saveChildNode) { final Node childNode = new Node(CHILD_NAME_1); final Node parentNode1 = new Node(PARENT_NAME_1, List.of(childNode)); @@ -191,7 +143,10 @@ void testStoreGraphWithCircularRelationWithTrippleSave() this.nodeRepository.save(parentNode1); this.nodeRepository.save(parentNode2); - this.nodeRepository.save(childNode); + if(saveChildNode) + { + this.nodeRepository.save(childNode); + } TestUtil.doBeforeAndAfterRestartOfDatastore( this.configuration, @@ -215,12 +170,6 @@ void testStoreGraphWithCircularRelationWithTrippleSave() ); } - //@formatter:off - /** - * □-□ - * □-┘ - **/ - //@formatter:on @Test void testModifyGraph() { From 170d9348ac965b4ca5f82184a2b0a74bbd56e4b7 Mon Sep 17 00:00:00 2001 From: AB Date: Wed, 26 Jun 2024 10:13:45 +0200 Subject: [PATCH 41/49] Sync --- spring-data-eclipse-store/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index 5b65f6fd..c933c415 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -403,6 +403,12 @@ ../.config/pmd/ruleset.xml + + **/benchmark/**/jmh_generated/** + + **/shared/**/Customer* + **/shared/**/Child* + From 55aa93906c1c2614425d9095313d43d20dde07fa Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 26 Jun 2024 11:40:45 +0200 Subject: [PATCH 42/49] Fixed some ID issues --- .../importer/EclipseStoreDataImporter.java | 8 +- .../store/repository/EclipseStoreStorage.java | 29 ++-- .../store/repository/IdSetterProvider.java | 2 +- .../EclipseStoreRepositoryFactory.java | 6 +- .../support/SimpleEclipseStoreRepository.java | 107 +++----------- .../support/copier/id/EntityGetterById.java | 24 ++++ .../support/copier/id/IdManager.java | 134 ++++++++++++++++++ .../support/copier/id/IdSetter.java | 13 +- .../support/copier/id/NotSettingIdSetter.java | 6 +- .../support/copier/id/SimpleIdSetter.java | 8 +- .../support/copier/id/strategy/IdFinder.java | 9 +- .../working/RecursiveWorkingCopier.java | 27 +++- .../SimpleRepositorySynchronizer.java | 1 - 13 files changed, 257 insertions(+), 117 deletions(-) create mode 100644 spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/EntityGetterById.java create mode 100644 spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java index 91134d7c..90d5dc5d 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java @@ -34,6 +34,7 @@ import software.xdev.spring.data.eclipse.store.repository.SupportedChecker; import software.xdev.spring.data.eclipse.store.repository.config.EclipseStoreClientConfiguration; import software.xdev.spring.data.eclipse.store.repository.support.SimpleEclipseStoreRepository; +import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager; import software.xdev.spring.data.eclipse.store.repository.support.copier.working.RecursiveWorkingCopier; import software.xdev.spring.data.eclipse.store.transactions.EclipseStoreTransactionManager; @@ -254,6 +255,7 @@ private void createRepositoryForType( private SimpleEclipseStoreRepository createEclipseStoreRepo(final Class domainClass) { final EclipseStoreStorage storageInstance = this.configuration.getStorageInstance(); + final IdManager idManager = storageInstance.ensureIdManager(domainClass); return new SimpleEclipseStoreRepository<>( storageInstance, new RecursiveWorkingCopier<>( @@ -262,10 +264,12 @@ private void createRepositoryForType( storageInstance, storageInstance, new SupportedChecker.Implementation(), - storageInstance + storageInstance, + idManager ), domainClass, - new EclipseStoreTransactionManager() + new EclipseStoreTransactionManager(), + idManager ); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java index 952dd0b1..41baf8dc 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java @@ -38,6 +38,7 @@ import software.xdev.spring.data.eclipse.store.repository.support.SimpleEclipseStoreRepository; import software.xdev.spring.data.eclipse.store.repository.support.concurrency.ReadWriteLock; import software.xdev.spring.data.eclipse.store.repository.support.concurrency.ReentrantJavaReadWriteLock; +import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager; import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdSetter; import software.xdev.spring.data.eclipse.store.repository.support.reposyncer.RepositorySynchronizer; import software.xdev.spring.data.eclipse.store.repository.support.reposyncer.SimpleRepositorySynchronizer; @@ -48,7 +49,7 @@ public class EclipseStoreStorage { private static final Logger LOG = LoggerFactory.getLogger(EclipseStoreStorage.class); private final Map, SimpleEclipseStoreRepository> entityClassToRepository = new HashMap<>(); - private final Map, IdSetter> idSetters = new ConcurrentHashMap<>(); + private final Map, IdManager> idManagers = new ConcurrentHashMap<>(); private final EclipseStoreStorageFoundationProvider foundationProvider; private EntitySetCollector entitySetCollector; private PersistableChecker persistenceChecker; @@ -317,7 +318,7 @@ public synchronized void stop() this.storageManager = null; this.root = null; this.registry.reset(); - this.idSetters.clear(); + this.idManagers.clear(); LOG.info("Stopped storage."); } else @@ -328,22 +329,32 @@ public synchronized void stop() ); } - @Override @SuppressWarnings("unchecked") - public IdSetter ensureIdSetter(final Class domainClass) + public IdManager ensureIdManager(final Class domainClass) { this.ensureEntitiesInRoot(); - return (IdSetter)this.idSetters.computeIfAbsent( + return (IdManager)this.idManagers.computeIfAbsent( domainClass, clazz -> - IdSetter.createIdSetter( - clazz, - id -> this.setLastId(clazz, id), - () -> this.getLastId(clazz) + new IdManager<>( + domainClass, + (IdSetter)IdSetter.createIdSetter( + clazz, + id -> this.setLastId(clazz, id), + () -> this.getLastId(clazz) + ), + this ) ); } + @Override + @SuppressWarnings("unchecked") + public IdSetter ensureIdSetter(final Class domainClass) + { + return (IdSetter)this.ensureIdManager(domainClass).getIdSetter(); + } + public Object getLastId(final Class entityClass) { return this.readWriteLock.read(() -> this.root.getLastId(entityClass)); diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java index 08b9536c..a5ea5416 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java @@ -20,5 +20,5 @@ public interface IdSetterProvider { - IdSetter ensureIdSetter(final Class domainClass); + IdSetter ensureIdSetter(final Class domainClass); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java index ec26a18a..e276d47a 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java @@ -80,7 +80,8 @@ private WorkingCopier createWorkingCopier( storage, storage, new SupportedChecker.Implementation(), - storage + storage, + storage.ensureIdManager(domainType) ); } @@ -100,7 +101,8 @@ protected Object getTargetRepository(@Nonnull final RepositoryInformation metada this.storage, this.createWorkingCopier(metadata.getDomainType(), this.storage), metadata.getDomainType(), - this.transactionManager + this.transactionManager, + this.storage.ensureIdManager(metadata.getDomainType()) ); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java index 7e30fc91..044f80b7 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java @@ -15,7 +15,6 @@ */ package software.xdev.spring.data.eclipse.store.repository.support; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -34,10 +33,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.repository.query.FluentQuery; -import software.xdev.spring.data.eclipse.store.exceptions.FieldAccessReflectionException; -import software.xdev.spring.data.eclipse.store.exceptions.NoIdFieldFoundException; import software.xdev.spring.data.eclipse.store.repository.EclipseStoreStorage; -import software.xdev.spring.data.eclipse.store.repository.access.modifier.FieldAccessModifier; import software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreCrudRepository; import software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreListCrudRepository; import software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreListPagingAndSortingRepositoryRepository; @@ -52,6 +48,7 @@ import software.xdev.spring.data.eclipse.store.repository.query.executors.ListQueryExecutor; import software.xdev.spring.data.eclipse.store.repository.query.executors.PageableQueryExecutor; import software.xdev.spring.data.eclipse.store.repository.query.executors.SingleOptionalQueryExecutor; +import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager; import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopier; import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopierResult; import software.xdev.spring.data.eclipse.store.transactions.EclipseStoreTransaction; @@ -72,37 +69,24 @@ public class SimpleEclipseStoreRepository private final Class domainClass; private final WorkingCopier copier; private final EclipseStoreTransactionManager transactionManager; - private Field idField; + private final IdManager idManager; public SimpleEclipseStoreRepository( final EclipseStoreStorage storage, final WorkingCopier copier, final Class domainClass, - final EclipseStoreTransactionManager transactionManager) + final EclipseStoreTransactionManager transactionManager, + final IdManager idManager + ) { this.storage = storage; this.domainClass = domainClass; + this.idManager = idManager; this.storage.registerEntity(domainClass, this); this.copier = copier; this.transactionManager = transactionManager; } - public Field getIdField() - { - if(this.idField == null) - { - final Optional foundIdField = IdFieldFinder.findIdField(this.domainClass); - if(foundIdField.isEmpty()) - { - throw new NoIdFieldFoundException(String.format( - "Could not find id field in class %s", - this.domainClass.getSimpleName())); - } - this.idField = foundIdField.get(); - } - return this.idField; - } - @SuppressWarnings("unchecked") public List saveBulk(final Collection entities) { @@ -180,31 +164,7 @@ public List saveAll(@Nonnull final Iterable entities) public Optional findById(@Nonnull final ID id) { return this.storage.getReadWriteLock().read( - () -> this.storage - .getEntityList(this.domainClass) - .parallelStream() - .filter( - entity -> - { - try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( - this.getIdField(), - entity)) - { - if(id.equals(fam.getValueOfField(entity))) - { - return true; - } - } - catch(final Exception e) - { - throw new FieldAccessReflectionException(String.format( - FieldAccessReflectionException.COULD_NOT_READ_FIELD, - this.getIdField().getName()), e); - } - return false; - } - ) - .findAny() + () -> this.idManager.findById(id) .map(foundEntity -> this.copier.copy(foundEntity)) ); } @@ -212,7 +172,9 @@ public Optional findById(@Nonnull final ID id) @Override public boolean existsById(@Nonnull final ID id) { - return this.findById(id).isPresent(); + return this.storage.getReadWriteLock().read( + () -> this.idManager.findById(id).isPresent() + ); } @Override @@ -233,37 +195,7 @@ public List findAllById(@Nonnull final Iterable idsToFind) // Must get copied as one list to keep same references objects the same. // (Example: If o1 and o2 (both part of the entity list) are referencing o3, // o3 should be the same no matter from where it is referenced. - () -> this.copier.copy( - this.storage - .getEntityList(this.domainClass) - .parallelStream() - .filter( - entity -> - { - try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( - this.getIdField(), - entity)) - { - final Object idOfEntity = fam.getValueOfField(entity); - for(final ID idToFind : idsToFind) - { - if(idToFind.equals(idOfEntity)) - { - return true; - } - } - } - catch(final Exception e) - { - throw new FieldAccessReflectionException(String.format( - FieldAccessReflectionException.COULD_NOT_READ_FIELD, - this.getIdField().getName()), e); - } - return false; - } - ) - .toList() - ) + () -> this.copier.copy(this.idManager.findAllById(idsToFind)) ); } @@ -276,11 +208,18 @@ public long count() @Override public void deleteById(@Nonnull final ID id) { - this.storage.getReadWriteLock().write( - () -> { - final Optional byId = this.findById(id); - byId.ifPresent(this::delete); - } + final EclipseStoreTransaction transaction = this.transactionManager.getTransaction(); + transaction.addAction(() -> + this.storage.getReadWriteLock().write( + () -> { + this + .idManager + .findById(id) + .ifPresent( + foundEntity -> this.storage.delete(this.domainClass, foundEntity) + ); + } + ) ); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/EntityGetterById.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/EntityGetterById.java new file mode 100644 index 00000000..91e44a5c --- /dev/null +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/EntityGetterById.java @@ -0,0 +1,24 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * 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 software.xdev.spring.data.eclipse.store.repository.support.copier.id; + +import java.util.Optional; + + +public interface EntityGetterById +{ + Optional findById(ID id); +} diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java new file mode 100644 index 00000000..a6a4efd8 --- /dev/null +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java @@ -0,0 +1,134 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * 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 software.xdev.spring.data.eclipse.store.repository.support.copier.id; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Optional; + +import jakarta.annotation.Nonnull; + +import software.xdev.spring.data.eclipse.store.exceptions.FieldAccessReflectionException; +import software.xdev.spring.data.eclipse.store.exceptions.NoIdFieldFoundException; +import software.xdev.spring.data.eclipse.store.repository.EclipseStoreStorage; +import software.xdev.spring.data.eclipse.store.repository.access.modifier.FieldAccessModifier; +import software.xdev.spring.data.eclipse.store.repository.support.IdFieldFinder; + + +public class IdManager implements EntityGetterById +{ + private final Class domainClass; + private final IdSetter idSetter; + private final Optional idField; + private final EclipseStoreStorage storage; + + public IdManager( + final Class domainClass, + final IdSetter idSetter, + final EclipseStoreStorage storage + ) + { + this.domainClass = domainClass; + this.idSetter = idSetter; + this.storage = storage; + this.idField = IdFieldFinder.findIdField(this.domainClass); + } + + public Field ensureIdField() + { + if(this.idField.isEmpty()) + { + throw new NoIdFieldFoundException(String.format( + "Could not find id field in class %s", + this.domainClass.getSimpleName())); + } + return this.idField.get(); + } + + @Override + public Optional findById(@Nonnull final ID id) + { + this.ensureIdField(); + return this.storage.getReadWriteLock().read( + () -> this.storage + .getEntityList(this.domainClass) + .parallelStream() + .filter( + entity -> + { + try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( + this.ensureIdField(), + entity)) + { + if(id.equals(fam.getValueOfField(entity))) + { + return true; + } + } + catch(final Exception e) + { + throw new FieldAccessReflectionException(String.format( + FieldAccessReflectionException.COULD_NOT_READ_FIELD, + this.ensureIdField().getName()), e); + } + return false; + } + ) + .findAny() + ); + } + + public List findAllById(@Nonnull final Iterable idsToFind) + { + this.ensureIdField(); + return this.storage.getReadWriteLock().read( + () -> this.storage + .getEntityList(this.domainClass) + .parallelStream() + .filter( + entity -> + { + try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( + this.ensureIdField(), + entity)) + { + final Object idOfEntity = fam.getValueOfField(entity); + for(final ID idToFind : idsToFind) + { + if(idToFind.equals(idOfEntity)) + { + return true; + } + } + } + catch(final Exception e) + { + throw new FieldAccessReflectionException(String.format( + FieldAccessReflectionException.COULD_NOT_READ_FIELD, + this.ensureIdField().getName()), e); + } + return false; + } + ) + .toList() + ); + } + + public IdSetter getIdSetter() + { + return this.idSetter; + } +} diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java index 9a2f1da0..9fc28bf8 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java @@ -31,9 +31,9 @@ * A IdSetter must be unique in one storage for one entity-class. It creates Ids and therefore must know all * existing entities of one class. */ -public interface IdSetter +public interface IdSetter { - static IdSetter createIdSetter( + static IdSetter createIdSetter( final Class classWithId, final Consumer lastIdPersister, final Supplier lastIdGetter) @@ -44,14 +44,14 @@ static IdSetter createIdSetter( final Optional idField = IdFieldFinder.findIdField(classWithId); if(idField.isEmpty()) { - return new NotSettingIdSetter<>(); + return (IdSetter)new NotSettingIdSetter(); } final GeneratedValue generatedValueAnnotation = idField.get().getAnnotation(GeneratedValue.class); if(generatedValueAnnotation == null) { - return new NotSettingIdSetter<>(); + return (IdSetter)new NotSettingIdSetter(); } - return new SimpleIdSetter<>( + return new SimpleIdSetter( idField.get(), IdFinder.createIdFinder(idField.get(), generatedValueAnnotation, lastIdGetter), lastIdPersister); @@ -60,6 +60,7 @@ static IdSetter createIdSetter( /** * This method makes sure, that an id is set for the given object. If it is already set (not null), then nothing is * done. If it is not set, a new one will be generated and set. + * @return the existing or newly created id or empty optional if no id is used */ - void ensureId(T objectToSetIdIn); + ID ensureId(T objectToSetIdIn); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java index c299b55d..a5f98e11 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java @@ -15,11 +15,11 @@ */ package software.xdev.spring.data.eclipse.store.repository.support.copier.id; -public class NotSettingIdSetter implements IdSetter +public class NotSettingIdSetter implements IdSetter { @Override - public void ensureId(final T objectToSetIdIn) + public Void ensureId(final T objectToSetIdIn) { - // Don't need to do anything + return null; } } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java index e59bc75f..593c39ef 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java @@ -25,7 +25,7 @@ import software.xdev.spring.data.eclipse.store.repository.support.copier.id.strategy.IdFinder; -public class SimpleIdSetter implements IdSetter +public class SimpleIdSetter implements IdSetter { private final IdFinder idFinder; private final Field idField; @@ -51,19 +51,21 @@ private void checkIfIdFieldIsFinal() } @Override - public void ensureId(final T objectToSetIdIn) + public ID ensureId(final T objectToSetIdIn) { try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( this.idField, objectToSetIdIn)) { - final Object existingId = fam.getValueOfField(objectToSetIdIn); + final ID existingId = (ID)fam.getValueOfField(objectToSetIdIn); if(existingId == null) { final ID newId = this.idFinder.findId(); fam.writeValueOfField(objectToSetIdIn, newId, true); this.lastIdPersister.accept(newId); + return newId; } + return existingId; } catch(final Exception e) { diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/strategy/IdFinder.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/strategy/IdFinder.java index 2618fa2b..88391777 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/strategy/IdFinder.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/strategy/IdFinder.java @@ -21,6 +21,7 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; + import software.xdev.spring.data.eclipse.store.exceptions.IdGeneratorNotSupportedException; import software.xdev.spring.data.eclipse.store.repository.support.copier.id.strategy.auto.AutoIntegerIdFinder; import software.xdev.spring.data.eclipse.store.repository.support.copier.id.strategy.auto.AutoLongIdFinder; @@ -34,7 +35,7 @@ public interface IdFinder { @SuppressWarnings({"java:S1452", "TypeParameterExplicitlyExtendsObject"}) - static IdFinder createIdFinder( + static IdFinder createIdFinder( final Field idField, final GeneratedValue generatedValueAnnotation, final Supplier lastIdGetter) @@ -44,15 +45,15 @@ static IdFinder createIdFinder( { if(Integer.class.isAssignableFrom(idField.getType()) || int.class.isAssignableFrom(idField.getType())) { - return new AutoIntegerIdFinder(lastIdGetter); + return (IdFinder)new AutoIntegerIdFinder(lastIdGetter); } else if(idField.getType().equals(String.class)) { - return new AutoStringIdFinder(lastIdGetter); + return (IdFinder)new AutoStringIdFinder(lastIdGetter); } else if(Long.class.isAssignableFrom(idField.getType()) || long.class.isAssignableFrom(idField.getType())) { - return new AutoLongIdFinder(lastIdGetter); + return (IdFinder)new AutoLongIdFinder(lastIdGetter); } } throw new IdGeneratorNotSupportedException(String.format( diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java index c03949fa..62b3d368 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java @@ -24,6 +24,7 @@ import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.Objects; +import java.util.Optional; import java.util.TreeMap; import java.util.TreeSet; @@ -41,6 +42,7 @@ import software.xdev.spring.data.eclipse.store.repository.access.modifier.FieldAccessModifier; import software.xdev.spring.data.eclipse.store.repository.lazy.SpringDataEclipseStoreLazy; import software.xdev.spring.data.eclipse.store.repository.support.copier.DataTypeUtil; +import software.xdev.spring.data.eclipse.store.repository.support.copier.id.EntityGetterById; import software.xdev.spring.data.eclipse.store.repository.support.copier.registering.RegisteringObjectCopier; import software.xdev.spring.data.eclipse.store.repository.support.copier.registering.RegisteringStorageToWorkingCopyCopier; import software.xdev.spring.data.eclipse.store.repository.support.copier.registering.RegisteringWorkingCopyToStorageCopier; @@ -58,6 +60,7 @@ public class RecursiveWorkingCopier implements WorkingCopier private final IdSetterProvider idSetterProvider; private final Class domainClass; private final PersistableChecker persistableChecker; + private final EntityGetterById entityGetterById; public RecursiveWorkingCopier( final Class domainClass, @@ -65,7 +68,9 @@ public RecursiveWorkingCopier( final IdSetterProvider idSetterProvider, final PersistableChecker persistableChecker, final SupportedChecker supportedChecker, - final ObjectSwizzling objectSwizzling) + final ObjectSwizzling objectSwizzling, + final EntityGetterById entityGetterById + ) { this.domainClass = domainClass; this.registry = registry; @@ -75,6 +80,7 @@ public RecursiveWorkingCopier( new RegisteringStorageToWorkingCopyCopier(registry, supportedChecker, objectSwizzling, this); this.idSetterProvider = idSetterProvider; this.persistableChecker = persistableChecker; + this.entityGetterById = entityGetterById; } @Override @@ -138,7 +144,8 @@ public E getOrCreateObjectForDatastore( { return null; } - this.idSetterProvider.ensureIdSetter((Class)workingCopy.getClass()).ensureId(workingCopy); + final Object usedId = + this.idSetterProvider.ensureIdSetter((Class)workingCopy.getClass()).ensureId(workingCopy); final E originalObject = this.registry.getOriginalObjectFromWorkingCopy(workingCopy); if(originalObject != null) { @@ -150,6 +157,22 @@ public E getOrCreateObjectForDatastore( return originalObject; } + if(usedId != null) + { + // If an id is used, we need to check if an entity with this id already exists and perhaps merge into + // that object. + final Optional existingEntity = this.entityGetterById.findById(usedId); + if(existingEntity.isPresent()) + { + if(mergeValues) + { + this.mergeValues(workingCopy, existingEntity.get(), alreadyMergedTargets, changedCollector); + } + changedCollector.collectChangedObject(existingEntity.get()); + return (E)existingEntity.get(); + } + } + // The object to merge back is not a working copy, but a originalObject. // Therefore, we create a copy to persist this in the storage. final E objectForDatastore = this.genericCopy(workingCopy, true); diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java index 7a4ee4ed..c346c66f 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/reposyncer/SimpleRepositorySynchronizer.java @@ -53,7 +53,6 @@ public SimpleRepositorySynchronizer(final Root root) final IdentitySet entityListForCurrentObject = this.root.getEntityList(objectInGraphClass); if(entityListForCurrentObject != null) { - if(!entityListForCurrentObject.contains(objectInGraph)) { entityListForCurrentObject.add(objectInGraph); From fc316c8253affc8adaede651ba37372d4825ebff Mon Sep 17 00:00:00 2001 From: XDEV Renovate Bot Date: Thu, 27 Jun 2024 02:22:57 +0000 Subject: [PATCH 43/49] Update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.6.1 --- spring-data-eclipse-store/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index c933c415..02d54ff7 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -202,7 +202,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.6.0 + 3.6.1 From 5769df9664aa551431aa5d6d2b023ba9b83b24a9 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Thu, 27 Jun 2024 09:51:12 +0200 Subject: [PATCH 44/49] Entities with same IDs are now replaced --- .../store/jpa/integration/JpaImportTest.java | 2 +- .../PersonToTestInEclipseStore.java | 5 +- .../importer/EclipseStoreDataImporter.java | 3 +- .../store/repository/EclipseStoreStorage.java | 12 +- ...erProvider.java => IdManagerProvider.java} | 6 +- .../EclipseStoreRepositoryFactory.java | 3 +- .../support/SimpleEclipseStoreRepository.java | 25 +++- .../support/copier/id/IdGetter.java | 21 +++ .../support/copier/id/IdManager.java | 130 +++++++++++------- .../support/copier/id/IdSetter.java | 15 +- .../support/copier/id/NotSettingIdSetter.java | 12 +- .../support/copier/id/SimpleIdSetter.java | 16 ++- .../working/RecursiveWorkingCopier.java | 30 ++-- .../integration/isolated/tests/id/IdTest.java | 104 ++++++++++---- .../tests/id/IdTestConfiguration.java | 13 ++ .../TransactionsAnnotationTest.java | 4 +- .../tests/transactions/TransactionsTest.java | 4 +- 17 files changed, 279 insertions(+), 126 deletions(-) rename spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/{IdSetterProvider.java => IdManagerProvider.java} (85%) create mode 100644 spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdGetter.java diff --git a/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportTest.java b/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportTest.java index aebba495..b1a3bf03 100644 --- a/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportTest.java +++ b/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/JpaImportTest.java @@ -49,7 +49,7 @@ class JpaImportTest @Test void testBasicSaveAndFindSingleRecords() { - final PersonToTestInEclipseStore customer = new PersonToTestInEclipseStore("", ""); + final PersonToTestInEclipseStore customer = new PersonToTestInEclipseStore("1", "", ""); this.personToTestInEclipseStoreRepository.save(customer); final List customers = this.personToTestInEclipseStoreRepository.findAll(); diff --git a/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/repository/PersonToTestInEclipseStore.java b/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/repository/PersonToTestInEclipseStore.java index f57f21e2..ff0b17f2 100644 --- a/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/repository/PersonToTestInEclipseStore.java +++ b/spring-data-eclipse-store-jpa/src/test/java/software/xdev/spring/data/eclipse/store/jpa/integration/repository/PersonToTestInEclipseStore.java @@ -8,13 +8,14 @@ public class PersonToTestInEclipseStore { @Id - private String id; + private final String id; private final String firstName; private final String lastName; - public PersonToTestInEclipseStore(final String firstName, final String lastName) + public PersonToTestInEclipseStore(final String id, final String firstName, final String lastName) { + this.id = id; this.firstName = firstName; this.lastName = lastName; } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java index 90d5dc5d..44322910 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java @@ -264,8 +264,7 @@ private void createRepositoryForType( storageInstance, storageInstance, new SupportedChecker.Implementation(), - storageInstance, - idManager + storageInstance ), domainClass, new EclipseStoreTransactionManager(), diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java index 41baf8dc..f05422f6 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java @@ -45,7 +45,7 @@ public class EclipseStoreStorage - implements EntityListProvider, IdSetterProvider, PersistableChecker, ObjectSwizzling + implements EntityListProvider, IdManagerProvider, PersistableChecker, ObjectSwizzling { private static final Logger LOG = LoggerFactory.getLogger(EclipseStoreStorage.class); private final Map, SimpleEclipseStoreRepository> entityClassToRepository = new HashMap<>(); @@ -329,6 +329,7 @@ public synchronized void stop() ); } + @Override @SuppressWarnings("unchecked") public IdManager ensureIdManager(final Class domainClass) { @@ -338,7 +339,7 @@ public IdManager ensureIdManager(final Class domainClass) clazz -> new IdManager<>( domainClass, - (IdSetter)IdSetter.createIdSetter( + (IdSetter)IdSetter.createIdSetter( clazz, id -> this.setLastId(clazz, id), () -> this.getLastId(clazz) @@ -348,13 +349,6 @@ public IdManager ensureIdManager(final Class domainClass) ); } - @Override - @SuppressWarnings("unchecked") - public IdSetter ensureIdSetter(final Class domainClass) - { - return (IdSetter)this.ensureIdManager(domainClass).getIdSetter(); - } - public Object getLastId(final Class entityClass) { return this.readWriteLock.read(() -> this.root.getLastId(entityClass)); diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdManagerProvider.java similarity index 85% rename from spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java rename to spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdManagerProvider.java index a5ea5416..dbe88f61 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdSetterProvider.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdManagerProvider.java @@ -15,10 +15,10 @@ */ package software.xdev.spring.data.eclipse.store.repository; -import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdSetter; +import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager; -public interface IdSetterProvider +public interface IdManagerProvider { - IdSetter ensureIdSetter(final Class domainClass); + IdManager ensureIdManager(final Class domainClass); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java index e276d47a..ee5b0996 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java @@ -80,8 +80,7 @@ private WorkingCopier createWorkingCopier( storage, storage, new SupportedChecker.Implementation(), - storage, - storage.ensureIdManager(domainType) + storage ); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java index 044f80b7..799efe90 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/SimpleEclipseStoreRepository.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import jakarta.annotation.Nonnull; @@ -103,9 +104,18 @@ private void uncachedStore(final Collection entities) { LOG.debug("Saving {} entities...", entities.size()); } + + this.checkEntityForNull(entities); + this.idManager.checkIds(entities); + + Stream entitiesStream = entities.stream(); + if(this.isMergeParallelizable()) + { + entitiesStream = entities.parallelStream(); + } + final List> results = - this.checkEntityForNull(entities) - .parallelStream() + entitiesStream .map(this.copier::mergeBack) .toList(); final Set nonEntitiesToStore = @@ -129,6 +139,17 @@ private void uncachedStore(final Collection entities) ); } + /** + * If the entities class to merge has an id, it is not possible to parallelize the merge. To search for existing + * ids, we need a read lock. Since we are having a write lock to store the entities, we can not release the lock + * and + * would be stuck in a deadlock. + */ + private boolean isMergeParallelizable() + { + return !this.idManager.hasIdField(); + } + @Override @Nonnull public S save(@Nonnull final S entity) diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdGetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdGetter.java new file mode 100644 index 00000000..d10b5f06 --- /dev/null +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdGetter.java @@ -0,0 +1,21 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * 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 software.xdev.spring.data.eclipse.store.repository.support.copier.id; + +public interface IdGetter +{ + ID getId(T objectToSetIdIn) throws Exception; +} diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java index a6a4efd8..3340fdbb 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java @@ -16,8 +16,11 @@ package software.xdev.spring.data.eclipse.store.repository.support.copier.id; import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.stream.StreamSupport; import jakarta.annotation.Nonnull; @@ -28,16 +31,16 @@ import software.xdev.spring.data.eclipse.store.repository.support.IdFieldFinder; -public class IdManager implements EntityGetterById +public class IdManager implements EntityGetterById, IdGetter { private final Class domainClass; - private final IdSetter idSetter; + private final IdSetter idSetter; private final Optional idField; private final EclipseStoreStorage storage; public IdManager( final Class domainClass, - final IdSetter idSetter, + final IdSetter idSetter, final EclipseStoreStorage storage ) { @@ -65,28 +68,8 @@ public Optional findById(@Nonnull final ID id) return this.storage.getReadWriteLock().read( () -> this.storage .getEntityList(this.domainClass) - .parallelStream() - .filter( - entity -> - { - try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( - this.ensureIdField(), - entity)) - { - if(id.equals(fam.getValueOfField(entity))) - { - return true; - } - } - catch(final Exception e) - { - throw new FieldAccessReflectionException(String.format( - FieldAccessReflectionException.COULD_NOT_READ_FIELD, - this.ensureIdField().getName()), e); - } - return false; - } - ) + .stream() + .filter(entity -> id.equals(this.getId(entity))) .findAny() ); } @@ -97,38 +80,91 @@ public List findAllById(@Nonnull final Iterable idsToFind) return this.storage.getReadWriteLock().read( () -> this.storage .getEntityList(this.domainClass) - .parallelStream() + .stream() .filter( entity -> { - try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( - this.ensureIdField(), - entity)) - { - final Object idOfEntity = fam.getValueOfField(entity); - for(final ID idToFind : idsToFind) - { - if(idToFind.equals(idOfEntity)) - { - return true; - } - } - } - catch(final Exception e) - { - throw new FieldAccessReflectionException(String.format( - FieldAccessReflectionException.COULD_NOT_READ_FIELD, - this.ensureIdField().getName()), e); - } - return false; + final Object idOfEntity = this.getId(entity); + return StreamSupport + .stream(idsToFind.spliterator(), false) + .anyMatch(idToFind -> idToFind.equals(idOfEntity)); } ) .toList() ); } - public IdSetter getIdSetter() + public IdSetter getIdSetter() { return this.idSetter; } + + @Override + public ID getId(final T entity) + { + if(this.hasIdField()) + { + try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( + this.ensureIdField(), + entity)) + { + return (ID)fam.getValueOfField(entity); + } + catch(final Exception e) + { + throw new FieldAccessReflectionException(String.format( + FieldAccessReflectionException.COULD_NOT_READ_FIELD, + this.ensureIdField().getName()), e); + } + } + return null; + } + + public boolean hasIdField() + { + return this.idField.isPresent(); + } + + /** + * This method makes sure, that an id is set for the given object. If it is already set (not null), then nothing is + * done. If it is not set, a new one will be generated and set. + */ + public void ensureId(final T objectToSetIdIn) + { + this.getIdSetter().ensureId(objectToSetIdIn); + } + + public void checkIds(final Collection entities) + { + if(!this.hasIdField()) + { + return; + } + final List ids = entities + .stream() + .map(entity -> this.getId(entity)) + .toList(); + + if(!this.getIdSetter().isAutomaticSetter() && ids.contains(null)) + { + final Optional entityWithNullId = + entities.stream().filter(entity -> this.getId(entity) == null).findAny(); + if(entityWithNullId.isPresent()) + { + throw new IllegalArgumentException( + "Invalid ID (null) for entity " + entityWithNullId + ); + } + } + + final List multipleEqualIds = ids.stream() + .filter(id -> Collections.frequency(ids, id) > 1) + .toList(); + if(!multipleEqualIds.isEmpty()) + { + throw new IllegalArgumentException( + "Same ID %s is set multiple times in one save call ".formatted(multipleEqualIds.get(0)) + ); + } + } } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java index 9fc28bf8..33d02283 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java @@ -31,9 +31,9 @@ * A IdSetter must be unique in one storage for one entity-class. It creates Ids and therefore must know all * existing entities of one class. */ -public interface IdSetter +public interface IdSetter { - static IdSetter createIdSetter( + static IdSetter createIdSetter( final Class classWithId, final Consumer lastIdPersister, final Supplier lastIdGetter) @@ -44,14 +44,14 @@ static IdSetter createIdSetter( final Optional idField = IdFieldFinder.findIdField(classWithId); if(idField.isEmpty()) { - return (IdSetter)new NotSettingIdSetter(); + return new NotSettingIdSetter<>(); } final GeneratedValue generatedValueAnnotation = idField.get().getAnnotation(GeneratedValue.class); if(generatedValueAnnotation == null) { - return (IdSetter)new NotSettingIdSetter(); + return new NotSettingIdSetter<>(); } - return new SimpleIdSetter( + return new SimpleIdSetter<>( idField.get(), IdFinder.createIdFinder(idField.get(), generatedValueAnnotation, lastIdGetter), lastIdPersister); @@ -60,7 +60,8 @@ static IdSetter createIdSetter( /** * This method makes sure, that an id is set for the given object. If it is already set (not null), then nothing is * done. If it is not set, a new one will be generated and set. - * @return the existing or newly created id or empty optional if no id is used */ - ID ensureId(T objectToSetIdIn); + void ensureId(T objectToSetIdIn); + + boolean isAutomaticSetter(); } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java index a5f98e11..1ee781f2 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/NotSettingIdSetter.java @@ -15,11 +15,17 @@ */ package software.xdev.spring.data.eclipse.store.repository.support.copier.id; -public class NotSettingIdSetter implements IdSetter +public class NotSettingIdSetter implements IdSetter { @Override - public Void ensureId(final T objectToSetIdIn) + public void ensureId(final T objectToSetIdIn) { - return null; + // Do nothing because no id generation is needed + } + + @Override + public boolean isAutomaticSetter() + { + return false; } } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java index 593c39ef..30aa830a 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/SimpleIdSetter.java @@ -25,7 +25,7 @@ import software.xdev.spring.data.eclipse.store.repository.support.copier.id.strategy.IdFinder; -public class SimpleIdSetter implements IdSetter +public class SimpleIdSetter implements IdSetter { private final IdFinder idFinder; private final Field idField; @@ -51,25 +51,29 @@ private void checkIfIdFieldIsFinal() } @Override - public ID ensureId(final T objectToSetIdIn) + public void ensureId(final T objectToSetIdIn) { try(final FieldAccessModifier fam = FieldAccessModifier.prepareForField( this.idField, objectToSetIdIn)) { - final ID existingId = (ID)fam.getValueOfField(objectToSetIdIn); + final Object existingId = fam.getValueOfField(objectToSetIdIn); if(existingId == null) { - final ID newId = this.idFinder.findId(); + final ID newId = (ID)this.idFinder.findId(); fam.writeValueOfField(objectToSetIdIn, newId, true); this.lastIdPersister.accept(newId); - return newId; } - return existingId; } catch(final Exception e) { throw new FieldAccessReflectionException(this.idField, e); } } + + @Override + public boolean isAutomaticSetter() + { + return true; + } } diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java index 62b3d368..7db05532 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java @@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory; import software.xdev.spring.data.eclipse.store.exceptions.MergeFailedException; -import software.xdev.spring.data.eclipse.store.repository.IdSetterProvider; +import software.xdev.spring.data.eclipse.store.repository.IdManagerProvider; import software.xdev.spring.data.eclipse.store.repository.PersistableChecker; import software.xdev.spring.data.eclipse.store.repository.SupportedChecker; import software.xdev.spring.data.eclipse.store.repository.WorkingCopyRegistry; @@ -42,7 +42,7 @@ import software.xdev.spring.data.eclipse.store.repository.access.modifier.FieldAccessModifier; import software.xdev.spring.data.eclipse.store.repository.lazy.SpringDataEclipseStoreLazy; import software.xdev.spring.data.eclipse.store.repository.support.copier.DataTypeUtil; -import software.xdev.spring.data.eclipse.store.repository.support.copier.id.EntityGetterById; +import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager; import software.xdev.spring.data.eclipse.store.repository.support.copier.registering.RegisteringObjectCopier; import software.xdev.spring.data.eclipse.store.repository.support.copier.registering.RegisteringStorageToWorkingCopyCopier; import software.xdev.spring.data.eclipse.store.repository.support.copier.registering.RegisteringWorkingCopyToStorageCopier; @@ -51,25 +51,23 @@ /** * Creates copies and puts them back. Recognizes already persisted Objects and checks them for changes as well. */ -public class RecursiveWorkingCopier implements WorkingCopier +public class RecursiveWorkingCopier implements WorkingCopier { private static final Logger LOG = LoggerFactory.getLogger(RecursiveWorkingCopier.class); private final RegisteringObjectCopier workingCopyToStorageCopier; private final RegisteringObjectCopier storageToWorkingCopyCopier; private final WorkingCopyRegistry registry; - private final IdSetterProvider idSetterProvider; + private final IdManagerProvider idManagerProvider; private final Class domainClass; private final PersistableChecker persistableChecker; - private final EntityGetterById entityGetterById; public RecursiveWorkingCopier( final Class domainClass, final WorkingCopyRegistry registry, - final IdSetterProvider idSetterProvider, + final IdManagerProvider idManagerProvider, final PersistableChecker persistableChecker, final SupportedChecker supportedChecker, - final ObjectSwizzling objectSwizzling, - final EntityGetterById entityGetterById + final ObjectSwizzling objectSwizzling ) { this.domainClass = domainClass; @@ -78,9 +76,8 @@ public RecursiveWorkingCopier( new RegisteringWorkingCopyToStorageCopier(registry, supportedChecker, objectSwizzling, this); this.storageToWorkingCopyCopier = new RegisteringStorageToWorkingCopyCopier(registry, supportedChecker, objectSwizzling, this); - this.idSetterProvider = idSetterProvider; + this.idManagerProvider = idManagerProvider; this.persistableChecker = persistableChecker; - this.entityGetterById = entityGetterById; } @Override @@ -144,8 +141,10 @@ public E getOrCreateObjectForDatastore( { return null; } - final Object usedId = - this.idSetterProvider.ensureIdSetter((Class)workingCopy.getClass()).ensureId(workingCopy); + final IdManager idManager = + this.idManagerProvider.ensureIdManager((Class)workingCopy.getClass()); + + idManager.ensureId(workingCopy); final E originalObject = this.registry.getOriginalObjectFromWorkingCopy(workingCopy); if(originalObject != null) { @@ -157,11 +156,12 @@ public E getOrCreateObjectForDatastore( return originalObject; } - if(usedId != null) + final Object id = idManager.getId(workingCopy); + if(id != null) { // If an id is used, we need to check if an entity with this id already exists and perhaps merge into // that object. - final Optional existingEntity = this.entityGetterById.findById(usedId); + final Optional existingEntity = idManager.findById(id); if(existingEntity.isPresent()) { if(mergeValues) @@ -169,7 +169,7 @@ public E getOrCreateObjectForDatastore( this.mergeValues(workingCopy, existingEntity.get(), alreadyMergedTargets, changedCollector); } changedCollector.collectChangedObject(existingEntity.get()); - return (E)existingEntity.get(); + return existingEntity.get(); } } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java index 03f7b67f..d3dcb25a 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTest.java @@ -24,6 +24,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; import software.xdev.spring.data.eclipse.store.helper.TestData; import software.xdev.spring.data.eclipse.store.helper.TestUtil; @@ -307,17 +309,9 @@ void testSaveSingleWithNoAutoIdInteger( { final CustomerWithIdIntegerNoAutoGenerate customer1 = new CustomerWithIdIntegerNoAutoGenerate(); - customerRepository.save(customer1); - - TestUtil.doBeforeAndAfterRestartOfDatastore( - this.configuration, - () -> { - final List loadedCustomer = - TestUtil.iterableToList(customerRepository.findAll()); - Assertions.assertEquals(1, loadedCustomer.size()); - Assertions.assertNull(loadedCustomer.get(0).getId()); - Assertions.assertEquals(customer1, loadedCustomer.get(0)); - } + Assertions.assertThrows( + IllegalArgumentException.class, + () -> customerRepository.save(customer1) ); } @@ -455,7 +449,8 @@ void testReplaceWithAutoId(@Autowired final CustomerWithIdIntegerRepository cust customerRepository.save(existingCustomer); final Integer existingId = customerRepository.findAll().iterator().next().getId(); - final CustomerWithIdInteger newCustomer = new CustomerWithIdInteger(existingId, + final CustomerWithIdInteger newCustomer = new CustomerWithIdInteger( + existingId, TestData.FIRST_NAME_ALTERNATIVE, TestData.LAST_NAME_ALTERNATIVE); customerRepository.save(newCustomer); @@ -481,18 +476,10 @@ void testReplaceWithIdSaveAll(@Autowired final CustomerWithIdIntegerNoAutoGenera final CustomerWithIdIntegerNoAutoGenerate newCustomer = new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME_ALTERNATIVE, TestData.LAST_NAME_ALTERNATIVE); - customerRepository.saveAll(List.of(existingCustomer, newCustomer)); - TestUtil.doBeforeAndAfterRestartOfDatastore( - this.configuration, - () -> { - final List loadedCustomer = - TestUtil.iterableToList(customerRepository.findAll()); - - Assertions.assertEquals(1, loadedCustomer.size()); - Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName()); - Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName()); - } + Assertions.assertThrows( + IllegalArgumentException.class, + () -> customerRepository.saveAll(List.of(existingCustomer, newCustomer)) ); } @@ -518,4 +505,75 @@ void testAddTwoWithId(@Autowired final CustomerWithIdIntegerNoAutoGenerateReposi } ); } + + @Test + void testIdsInMultipleTransactions( + @Autowired final CustomerWithIdIntegerNoAutoGenerateRepository customerRepository, + @Autowired final PlatformTransactionManager transactionManager + ) + { + new TransactionTemplate(transactionManager).execute( + status -> + { + final CustomerWithIdIntegerNoAutoGenerate existingCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME, TestData.LAST_NAME); + customerRepository.save(existingCustomer); + return null; + }); + + new TransactionTemplate(transactionManager).execute( + status -> + { + final CustomerWithIdIntegerNoAutoGenerate newCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME_ALTERNATIVE, + TestData.LAST_NAME_ALTERNATIVE); + customerRepository.save(newCustomer); + return null; + }); + + TestUtil.doBeforeAndAfterRestartOfDatastore( + this.configuration, + () -> { + final List loadedCustomer = + TestUtil.iterableToList(customerRepository.findAll()); + + Assertions.assertEquals(1, loadedCustomer.size()); + Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName()); + Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName()); + } + ); + } + + @Test + void testIdsInSingleTransactions( + @Autowired final CustomerWithIdIntegerNoAutoGenerateRepository customerRepository, + @Autowired final PlatformTransactionManager transactionManager + ) + { + new TransactionTemplate(transactionManager).execute( + status -> + { + final CustomerWithIdIntegerNoAutoGenerate existingCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME, TestData.LAST_NAME); + customerRepository.save(existingCustomer); + + final CustomerWithIdIntegerNoAutoGenerate newCustomer = + new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME_ALTERNATIVE, + TestData.LAST_NAME_ALTERNATIVE); + customerRepository.save(newCustomer); + return null; + }); + + TestUtil.doBeforeAndAfterRestartOfDatastore( + this.configuration, + () -> { + final List loadedCustomer = + TestUtil.iterableToList(customerRepository.findAll()); + + Assertions.assertEquals(1, loadedCustomer.size()); + Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName()); + Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName()); + } + ); + } } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java index 0743859f..b70d680c 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/id/IdTestConfiguration.java @@ -17,8 +17,12 @@ import org.eclipse.store.integrations.spring.boot.types.configuration.EclipseStoreProperties; import org.eclipse.store.integrations.spring.boot.types.factories.EmbeddedStorageFoundationFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; import software.xdev.spring.data.eclipse.store.integration.TestConfiguration; import software.xdev.spring.data.eclipse.store.repository.config.EnableEclipseStoreRepositories; @@ -35,4 +39,13 @@ protected IdTestConfiguration( { super(defaultEclipseStoreProperties, defaultEclipseStoreProvider); } + + @Bean + @Override + public PlatformTransactionManager transactionManager( + final ObjectProvider transactionManagerCustomizers + ) + { + return super.transactionManager(transactionManagerCustomizers); + } } diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsAnnotationTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsAnnotationTest.java index 0addc20b..d2fdfdcb 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsAnnotationTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsAnnotationTest.java @@ -45,8 +45,8 @@ public TransactionsAnnotationTest(final AccountRepository repository) void accountTransactionUnexpectedErrorAnnotation() { Assertions.assertThrows(RuntimeException.class, () -> { - final Account account1 = new Account(1, BigDecimal.TEN); - final Account account2 = new Account(2, BigDecimal.ZERO); + final Account account1 = new Account(3, BigDecimal.TEN); + final Account account2 = new Account(4, BigDecimal.ZERO); this.repository.saveAll(List.of(account1, account2)); throw new RuntimeException("Unexpected error"); diff --git a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java index 07b34579..6ddae199 100644 --- a/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java +++ b/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/transactions/TransactionsTest.java @@ -237,8 +237,8 @@ void findStoredEntityWithinTransaction(@Autowired final PlatformTransactionManag void accountNoTransactionUnexpectedError() { Assertions.assertThrows(RuntimeException.class, () -> { - final Account account1 = new Account(1, BigDecimal.TEN); - final Account account2 = new Account(2, BigDecimal.ZERO); + final Account account1 = new Account(3, BigDecimal.TEN); + final Account account2 = new Account(4, BigDecimal.ZERO); this.accountRepository.saveAll(List.of(account1, account2)); throw new RuntimeException("Unexpected error"); From 90c81e2e0678d180e00c1b376b3fdbf40b1966f7 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Thu, 27 Jun 2024 10:00:47 +0200 Subject: [PATCH 45/49] Refactoring --- .../working/RecursiveWorkingCopier.java | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java index 7db05532..3e40cc09 100644 --- a/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java +++ b/spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java @@ -51,7 +51,8 @@ /** * Creates copies and puts them back. Recognizes already persisted Objects and checks them for changes as well. */ -public class RecursiveWorkingCopier implements WorkingCopier +@SuppressWarnings("PMD.GodClass") +public class RecursiveWorkingCopier implements WorkingCopier { private static final Logger LOG = LoggerFactory.getLogger(RecursiveWorkingCopier.class); private final RegisteringObjectCopier workingCopyToStorageCopier; @@ -148,12 +149,13 @@ public E getOrCreateObjectForDatastore( final E originalObject = this.registry.getOriginalObjectFromWorkingCopy(workingCopy); if(originalObject != null) { - if(mergeValues) - { - this.mergeValues(workingCopy, originalObject, alreadyMergedTargets, changedCollector); - } - changedCollector.collectChangedObject(originalObject); - return originalObject; + return this.mergeValueIfNeeded( + workingCopy, + mergeValues, + alreadyMergedTargets, + changedCollector, + originalObject + ); } final Object id = idManager.getId(workingCopy); @@ -164,12 +166,13 @@ public E getOrCreateObjectForDatastore( final Optional existingEntity = idManager.findById(id); if(existingEntity.isPresent()) { - if(mergeValues) - { - this.mergeValues(workingCopy, existingEntity.get(), alreadyMergedTargets, changedCollector); - } - changedCollector.collectChangedObject(existingEntity.get()); - return existingEntity.get(); + return this.mergeValueIfNeeded( + workingCopy, + mergeValues, + alreadyMergedTargets, + changedCollector, + existingEntity.get() + ); } } @@ -183,6 +186,21 @@ public E getOrCreateObjectForDatastore( return objectForDatastore; } + private E mergeValueIfNeeded( + final E workingCopy, + final boolean mergeValues, + final MergedTargetsCollector alreadyMergedTargets, + final ChangedObjectCollector changedCollector, + final E existingEntity) + { + if(mergeValues) + { + this.mergeValues(workingCopy, existingEntity, alreadyMergedTargets, changedCollector); + } + changedCollector.collectChangedObject(existingEntity); + return existingEntity; + } + @Override public T getOriginal(final T workingCopy) { From 5424324c20c66e77671848b17ac01de7ee3b2745 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Thu, 27 Jun 2024 10:08:18 +0200 Subject: [PATCH 46/49] Update pom.xml --- spring-data-eclipse-store/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index 02d54ff7..59107721 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -408,6 +408,7 @@ **/shared/**/Customer* **/shared/**/Child* + **/isolated/**/Customer* From bffa74cf0a5d77f4ec348a1578a9a8d6a08decfc Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Thu, 27 Jun 2024 10:15:00 +0200 Subject: [PATCH 47/49] Update pom.xml --- spring-data-eclipse-store/pom.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index 59107721..e437fbbf 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -406,9 +406,7 @@ **/benchmark/**/jmh_generated/** - **/shared/**/Customer* - **/shared/**/Child* - **/isolated/**/Customer* + **/tests/** From b92fd2ba2e09d709a0420f2de7fd225b412b8467 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Thu, 27 Jun 2024 10:18:36 +0200 Subject: [PATCH 48/49] Update pom.xml --- spring-data-eclipse-store/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-eclipse-store/pom.xml b/spring-data-eclipse-store/pom.xml index e437fbbf..078c591f 100644 --- a/spring-data-eclipse-store/pom.xml +++ b/spring-data-eclipse-store/pom.xml @@ -406,7 +406,7 @@ **/benchmark/**/jmh_generated/** - **/tests/** + **/store/integration/** From 28239f8102ef682974760a7a4e4a633bb5d743dc Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Thu, 27 Jun 2024 10:25:16 +0200 Subject: [PATCH 49/49] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3569d9d..377a3011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 1.0.8 + +* Entities with same ID are replaced on saved and not added +* Updated Spring to version 3.3.1 + # 1.0.7 * QueryByExample now possible