From 4b25f3d9990cb109b35b8965aeca016dd549e02c Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Fri, 7 Mar 2025 22:22:40 +0100 Subject: [PATCH] Maintenance - Migrate build to Kotlin DSL - Update dependencies - Add partial IDE configuration - Add icon - Apply code style changes {minor} Signed-off-by: Esta Nagy --- .github/workflows/codeql-analysis.yml | 4 +- .github/workflows/gradle-ci.yml | 5 +- .github/workflows/gradle-oss-index-scan.yml | 2 +- .github/workflows/gradle.yml | 5 +- .gitignore | 7 +- .idea/codeStyles/Project.xml | 36 ++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/icon.png | Bin 0 -> 45534 bytes .idea/inspectionProfiles/Project_Default.xml | 19 + build.gradle | 290 -------------- build.gradle.kts | 352 ++++++++++++++++ config/ossindex/ossIndexAudit.gradle | 10 - config/ossindex/ossIndexAudit.gradle.kts | 11 + gradle/libs.versions.toml | 10 +- gradle/verification-metadata.xml | 377 +++++------------- settings.gradle | 1 - settings.gradle.kts | 1 + .../core/AbstractCacheServiceTemplate.java | 96 +++-- .../cacheonly/core/CacheRefreshStrategy.java | 57 +-- .../core/CachingServiceTemplate.java | 2 +- .../core/DefaultCacheServiceTemplate.java | 35 +- .../ConcurrentCacheServiceTemplate.java | 43 +- .../nagyesta/cacheonly/entity/CacheKey.java | 72 +--- .../concurrent/AsyncBatchServiceCaller.java | 3 +- .../raw/exception/BatchServiceException.java | 5 +- .../transform/BatchRequestTransformer.java | 2 +- .../transform/BatchResponseTransformer.java | 2 +- .../transform/NoOpPartialCacheSupport.java | 4 +- .../transform/PartialCacheSupport.java | 11 +- .../AbstractCollectionBasedTransformer.java | 16 +- .../common/AbstractMapBasedTransformer.java | 14 +- ...ractWrappedCollectionBasedTransformer.java | 38 +- .../AbstractWrappedMapBasedTransformer.java | 30 +- .../CollectionBasedRequestTransformer.java | 7 +- .../CollectionBasedResponseTransformer.java | 16 +- .../common/MapBasedRequestTransformer.java | 9 +- .../common/MapBasedResponseTransformer.java | 11 +- ...ppedCollectionBasedRequestTransformer.java | 32 +- ...pedCollectionBasedResponseTransformer.java | 32 +- .../WrappedMapBasedRequestTransformer.java | 24 +- .../WrappedMapBasedResponseTransformer.java | 24 +- .../core/CacheRefreshStrategyTest.java | 46 +-- ...ntCacheServiceTemplateIntegrationTest.java | 117 +++--- ...elCacheServiceTemplateIntegrationTest.java | 20 +- ...ckCacheServiceTemplateIntegrationTest.java | 66 ++- .../UnstableCacheServiceTemplateTest.java | 100 +++-- .../cacheonly/entity/CacheKeyTest.java | 18 +- .../example/parcel/raw/ParcelService.java | 2 +- .../parcel/response/ParcelResponse.java | 11 +- .../ParcelBatchResponseTransformer.java | 5 +- .../transform/ParcelPartialCacheSupport.java | 3 +- .../example/replies/CommentContext.java | 2 +- .../example/replies/raw/CommentService.java | 28 +- .../replies/request/ThreadRequest.java | 4 +- .../CommentBatchBasedRequestTransformer.java | 3 +- .../transform/CommentPartialCacheSupport.java | 2 +- .../cacheonly/example/stock/StockContext.java | 2 +- .../stock/raw/StockBatchServiceCaller.java | 3 +- .../UnstableCacheServiceTemplate.java | 4 +- .../UnstableConcurrentBatchServiceCaller.java | 9 +- .../unstable/UnstablePartialCacheSupport.java | 12 +- .../transform/CollectionWrapper.java | 15 +- .../cacheonly/transform/MapWrapper.java | 16 +- ...CollectionBasedRequestTransformerTest.java | 27 +- ...ollectionBasedResponseTransformerTest.java | 28 +- .../MapBasedRequestTransformerTest.java | 26 +- .../MapBasedResponseTransformerTest.java | 26 +- ...CollectionBasedRequestTransformerTest.java | 24 +- ...ollectionBasedResponseTransformerTest.java | 24 +- ...WrappedMapBasedRequestTransformerTest.java | 32 +- ...rappedMapBasedResponseTransformerTest.java | 40 +- 71 files changed, 1189 insertions(+), 1246 deletions(-) create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/icon.png create mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 build.gradle create mode 100644 build.gradle.kts delete mode 100644 config/ossindex/ossIndexAudit.gradle create mode 100644 config/ossindex/ossIndexAudit.gradle.kts delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 694a589..adbc339 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,6 +33,8 @@ on: - '.github/pr-labeler.yml' - 'renovate.json' - '.whitesource' + - '.idea/**' + - '.gitignore' permissions: # only required for workflows in private repositories @@ -71,4 +73,4 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 - name: Check OSS Index with Gradle - run: ./gradlew ossIndexAudit -PossIndexUsername=${{ secrets.OSS_INDEX_USER }} -PossIndexPassword=${{ secrets.OSS_INDEX_PASSWORD }} + run: ./gradlew ossIndexAudit -PossIndexUsername=${{ secrets.OSS_INDEX_USER }} -PossIndexPassword=${{ secrets.OSS_INDEX_PASSWORD }} --info diff --git a/.github/workflows/gradle-ci.yml b/.github/workflows/gradle-ci.yml index ac5a3f5..8556f94 100644 --- a/.github/workflows/gradle-ci.yml +++ b/.github/workflows/gradle-ci.yml @@ -24,6 +24,8 @@ on: - 'renovate.json' - '.whitesource' - 'config/ossindex/exclusions.txt' + - '.idea/**' + - '.gitignore' permissions: read-all @@ -70,5 +72,6 @@ jobs: uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: token: ${{ secrets.CODECOV_TOKEN }} - file: ./build/reports/jacoco/report.xml + files: ./build/reports/jacoco/report.xml + disable_search: true fail_ci_if_error: false diff --git a/.github/workflows/gradle-oss-index-scan.yml b/.github/workflows/gradle-oss-index-scan.yml index 5549c88..9e19e96 100644 --- a/.github/workflows/gradle-oss-index-scan.yml +++ b/.github/workflows/gradle-oss-index-scan.yml @@ -25,4 +25,4 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0 - name: Check dependencies with Gradle - run: ./gradlew ossIndexAudit -PossIndexUsername=${{ secrets.OSS_INDEX_USER }} -PossIndexPassword=${{ secrets.OSS_INDEX_PASSWORD }} + run: ./gradlew ossIndexAudit -PossIndexUsername=${{ secrets.OSS_INDEX_USER }} -PossIndexPassword=${{ secrets.OSS_INDEX_PASSWORD }} --info diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 3ef6753..048eb83 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -28,6 +28,8 @@ on: - 'gradlew' - 'gradlew.bat' - 'config/ossindex/exclusions.txt' + - '.idea/**' + - '.gitignore' permissions: read-all @@ -74,5 +76,6 @@ jobs: uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: token: ${{ secrets.CODECOV_TOKEN }} - file: ./build/reports/jacoco/report.xml + files: ./build/reports/jacoco/report.xml + disable_search: true fail_ci_if_error: false diff --git a/.gitignore b/.gitignore index 5629f08..93c59ee 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,12 @@ build/ .sts4-cache ### IntelliJ IDEA ### -.idea +.idea/** +!.idea/icon.png +!.idea/codeStyles +!.idea/codeStyles/** +!.idea/inspectionProfiles +!.idea/inspectionProfiles/** *.iws *.iml *.ipr diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..8fa0e68 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,36 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/icon.png b/.idea/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..02ed90da8de3726dfcee32c9c98cb23d50654838 GIT binary patch literal 45534 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 + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 325d497..0000000 --- a/build.gradle +++ /dev/null @@ -1,290 +0,0 @@ -//file:noinspection DependencyNotationArgument -plugins { - id 'java' - id 'checkstyle' - id 'jacoco' - id 'maven-publish' - id 'signing' - alias(libs.plugins.lombok) - alias(libs.plugins.versioner) - alias(libs.plugins.index.scan) - alias(libs.plugins.owasp.dependencycheck) - alias(libs.plugins.cyclonedx.bom) - alias(libs.plugins.licensee.plugin) - alias(libs.plugins.nexus.publish.plugin) -} - -group = 'com.github.nagyesta' - -apply from: "config/ossindex/ossIndexAudit.gradle" - -project.ext { - gitToken = project.hasProperty('githubToken') ? (project.property('githubToken') as String) : '' - gitUser = project.hasProperty('githubUser') ? (project.property('githubUser') as String) : '' - ossrhUser = project.hasProperty('ossrhUsername') ? (project.property('ossrhUsername') as String) : '' - ossrhPass = project.hasProperty('ossrhPassword') ? (project.property('ossrhPassword') as String) : '' - ossIndexUser = project.hasProperty('ossIndexUsername') ? (project.property('ossIndexUsername') as String) : '' - ossIndexPass = project.hasProperty('ossIndexPassword') ? (project.property('ossIndexPassword') as String) : '' - artifactDisplayName = "Cache-Only" - artifactDescription = "Cache-Only is a minimal library augmenting the Spring cache abstraction with a way for caching bulk API calls." - repoUrl = 'https://github.com/nagyesta/cache-only' - licenseName = 'MIT License' - licenseUrl = 'https://raw.githubusercontent.com/nagyesta/cache-only/main/LICENSE' - maintainerId = 'nagyesta' - maintainerName = 'Istvan Zoltan Nagy' - maintainerUrl = 'https://github.com/nagyesta/' - scmConnection = 'scm:git:https://github.com/nagyesta/cache-only.git' - scmProjectUrl = 'https://github.com/nagyesta/cache-only/' -} - -versioner { - startFrom { - major = 0 - minor = 0 - patch = 1 - } - match { - major = '{major}' - minor = '{minor}' - patch = '{patch}' - } - pattern { - pattern = "%M.%m.%p" - } - git { - authentication { - https { - token = project.ext.gitToken - } - } - } - tag { - prefix = 'v' - useCommitMessage = true - } -} - -versioner.apply() - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - withJavadocJar() - withSourcesJar() -} - -javadoc.options.addStringOption('Xdoclint:none', '-quiet') - -dependencies { - annotationProcessor libs.lombok - compileOnly libs.jetbrains.annotations - testCompileOnly libs.jetbrains.annotations - implementation libs.slf4j.api - implementation libs.commons.collections4 - implementation libs.spring.context.support - testImplementation libs.jupiter.core - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - testImplementation libs.mockito.core - testImplementation libs.spring.test - testImplementation libs.spring.context.support - testImplementation libs.logback.classic -} - -cyclonedxBom { - includeConfigs = ["runtimeClasspath"] - skipConfigs = ["compileClasspath", "testCompileClasspath"] - skipProjects = [] - projectType = "library" - schemaVersion = "1.5" - destination = file("build/reports") - outputName = "bom" - outputFormat = "json" - //noinspection UnnecessaryQualifiedReference - final def attachmentText = new org.cyclonedx.model.AttachmentText() - attachmentText.setText(file("LICENSE").readBytes().encodeBase64().toString()) - attachmentText.setEncoding("base64") - attachmentText.setContentType("text/plain") - //noinspection UnnecessaryQualifiedReference - final def license = new org.cyclonedx.model.License() - license.setName(project.ext.licenseName) - license.setLicenseText(attachmentText) - license.setUrl(project.ext.licenseUrl) - setLicenseChoice { - it.addLicense(license) - } -} - -licensee { - allow("Apache-2.0") - allow("MIT") -} - -tasks.register('copyLegalDocs', Copy.class) { - from file("${projectDir}/LICENSE") - from layout.buildDirectory.file("reports/licensee/artifacts.json").get().asFile - from layout.buildDirectory.file("reports/bom.json").get().asFile - into layout.buildDirectory.dir("resources/main/META-INF").get().asFile - rename('artifacts.json', 'dependency-licenses.json') - rename('bom.json', 'SBOM.json') -} -tasks.copyLegalDocs.dependsOn(tasks.licensee) -tasks.copyLegalDocs.dependsOn(tasks.cyclonedxBom) -tasks.javadoc.dependsOn(tasks.copyLegalDocs) -tasks.compileTestJava.dependsOn(tasks.copyLegalDocs) -tasks.checkstyleMain.dependsOn(tasks.copyLegalDocs) -tasks.processResources.finalizedBy(tasks.copyLegalDocs) - -jacocoTestReport { - reports { - xml.required.set(true) - xml.outputLocation.set(layout.buildDirectory.file("reports/jacoco/report.xml").get().asFile) - csv.required.set(false) - html.required.set(true) - html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco/html").get().asFile) - } -} - -test { - useJUnitPlatform() -} -test.finalizedBy jacocoTestReport -jacocoTestReport.finalizedBy jacocoTestCoverageVerification - -jacoco { - toolVersion = libs.versions.jacoco.get() -} - -jacocoTestCoverageVerification { - inputs.file(layout.buildDirectory.file("reports/jacoco/report.xml").get().asFile) - outputs.file(layout.buildDirectory.file("reports/jacoco/jacocoTestCoverageVerification").get().asFile) - - violationRules { - rule { - limit { - counter = 'LINE' - value = 'COVEREDRATIO' - minimum = 0.8 - } - limit { - counter = 'BRANCH' - value = 'COVEREDRATIO' - minimum = 0.8 - } - excludes = [ - ] - } - rule { - element = 'CLASS' - limit { - counter = 'LINE' - value = 'COVEREDRATIO' - minimum = 0.5 - } - limit { - counter = 'BRANCH' - value = 'COVEREDRATIO' - minimum = 0.5 - } - excludes = [ - "com.github.nagyesta.cacheonly.raw.BatchServiceCaller", - "com.github.nagyesta.cacheonly.transform.NoOpPartialCacheSupport" - ] - } - } - doLast { - layout.buildDirectory.file("reports/jacoco/jacocoTestCoverageVerification").get().asFile.write("Passed") - } -} -jar.dependsOn check - -tasks.withType(Checkstyle).configureEach { - configProperties = [base_dir: rootDir.toString(), cache_file: layout.buildDirectory.file("checkstyle/cacheFile").get().asFile] - reports { - xml.required.set(false) - html.required.set(true) - html.stylesheet resources.text - .fromFile(rootProject.file('config/checkstyle/checkstyle-stylesheet.xsl') as String) - } -} -checkstyle.toolVersion = libs.versions.checkstyle.get() - -nexusPublishing { - repositories { - sonatype { - username = project.ext.ossrhUser - password = project.ext.ossrhPass - } - } -} - -publishing { - repositories { - maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/nagyesta/cache-only") - credentials { - username = project.ext.gitUser - password = project.ext.gitToken - } - } - } - publications { - //noinspection GroovyAssignabilityCheck - mavenJava(MavenPublication) { - from components.java - artifactId = "${project.name}" - pom { - name = "${project.artifactDisplayName}" - description = "${project.artifactDescription}" - url = project.ext.repoUrl - licenses { - license { - name = project.ext.licenseName - url = project.ext.licenseUrl - } - } - developers { - developer { - id = project.ext.maintainerId - name = project.ext.maintainerName - url = project.ext.maintainerUrl - } - } - scm { - connection = project.ext.scmConnection - developerConnection = project.ext.scmConnection - url = project.ext.scmProjectUrl - } - withXml { - //noinspection GroovyImplicitNullArgumentCall - asNode().dependencies.'*'.findAll() { - it.scope.text() == 'runtime' - }.each { it.scope*.value = 'compile' } - } - } - } - } -} - - -//Disable metadata publishing and rely on Maven only -tasks.withType(GenerateModuleMetadata).configureEach { - enabled = false -} - -ossIndexAudit { - username = rootProject.ext.ossIndexUser - password = rootProject.ext.ossIndexPass - printBanner = false - colorEnabled = true - showAll = false - outputFormat = 'DEPENDENCY_GRAPH' - excludeVulnerabilityIds = rootProject.ext.ossIndexExclusions -} - -signing { - sign publishing.publications.mavenJava -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..b833e4f --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,352 @@ +@file:Suppress("SpellCheckingInspection") + +import groovy.util.Node +import groovy.util.NodeList +import org.apache.tools.ant.filters.ReplaceTokens +import org.sonatype.gradle.plugins.scan.ossindex.OutputFormat +import java.util.* + +plugins { + id("java") + jacoco + checkstyle + signing + `maven-publish` + alias(libs.plugins.lombok) + alias(libs.plugins.versioner) + alias(libs.plugins.index.scan) + alias(libs.plugins.owasp.dependencycheck) + alias(libs.plugins.cyclonedx.bom) + alias(libs.plugins.licensee.plugin) + alias(libs.plugins.nexus.publish.plugin) +} + +group = "com.github.nagyesta" + +apply("config/ossindex/ossIndexAudit.gradle.kts") + +buildscript { + fun optionalPropertyString(name: String): String { + return if (project.hasProperty(name)) { + project.property(name) as String + } else { + "" + } + } + + fun dockerAbortGroups(name: String): String { + return if (project.hasProperty(name)) { + "all" + } else { + "" + } + } + + extra.apply { + set("gitToken", optionalPropertyString("githubToken")) + set("gitUser", optionalPropertyString("githubUser")) + set("ossrhUser", optionalPropertyString("ossrhUsername")) + set("ossrhPass", optionalPropertyString("ossrhPassword")) + set("ossIndexUser", optionalPropertyString("ossIndexUsername")) + set("ossIndexPass", optionalPropertyString("ossIndexPassword")) + set("artifactDisplayName", "Cache-Only") + set( + "artifactDescription", + "Cache-Only is a minimal library augmenting the Spring cache abstraction with a way for caching bulk API calls." + ) + set("repoUrl", "https://github.com/nagyesta/cache-only") + set("licenseName", "MIT License") + set("licenseUrl", "https://raw.githubusercontent.com/nagyesta/cache-only/main/LICENSE") + set("maintainerId", "nagyesta") + set("maintainerName", "Istvan Zoltan Nagy") + set("maintainerUrl", "https://github.com/nagyesta/") + set("scmConnection", "scm:git:https://github.com/nagyesta/cache-only.git") + set("scmProjectUrl", "https://github.com/nagyesta/cache-only/") + set("githubMavenRepoUrl", "https://maven.pkg.github.com/nagyesta/cache-only") + set("ossrhMavenRepoUrl", "https://oss.sonatype.org/service/local/staging/deploy/maven2") + } +} + +versioner { + startFrom { + major = 0 + minor = 0 + patch = 1 + } + match { + major = "{major}" + minor = "{minor}" + patch = "{patch}" + } + pattern { + pattern = "%M.%m.%p" + } + git { + authentication { + https { + token = project.extra.get("gitToken").toString() + } + } + } + tag { + prefix = "v" + useCommitMessage = true + } +} + +versioner.apply() + +repositories { + mavenCentral() +} + +dependencies { + annotationProcessor(libs.lombok) + compileOnly(libs.jetbrains.annotations) + testCompileOnly(libs.jetbrains.annotations) + implementation(libs.slf4j.api) + implementation(libs.commons.collections4) + implementation(libs.spring.context.support) + testImplementation(libs.jupiter.core) + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testImplementation(libs.mockito.core) + testImplementation(libs.spring.test) + testImplementation(libs.spring.context.support) + testImplementation(libs.logback.classic) +} + +licensee { + allow("Apache-2.0") + allow("MIT") + allowUrl("https://opensource.org/license/mit") +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } + withJavadocJar() + withSourcesJar() +} + +val copyLegalDocs = tasks.register("copyLegalDocs") { + from(file("${project.projectDir}/LICENSE")) + from(layout.buildDirectory.file("reports/licensee/artifacts.json").get().asFile) + from(layout.buildDirectory.file("reports/bom.json").get().asFile) + into(layout.buildDirectory.dir("resources/main/META-INF").get().asFile) + rename("artifacts.json", "dependency-licenses.json") + rename("bom.json", "SBOM.json") +}.get() +copyLegalDocs.dependsOn(tasks.licensee) +copyLegalDocs.dependsOn(tasks.cyclonedxBom) +tasks.javadoc.get().dependsOn(copyLegalDocs) +tasks.compileJava.get().dependsOn(copyLegalDocs) +tasks.processResources.get().finalizedBy(copyLegalDocs) + +tasks.test { + useJUnitPlatform() + finalizedBy(tasks.getByName("jacocoTestReport")) +} + +project.tasks.processResources { + val tokens = mapOf("version" to project.version) + filesMatching("**/application.properties") { + filter("tokens" to tokens) + } +} + +tasks.javadoc.configure { + (options as StandardJavadocDocletOptions).addBooleanOption("Xdoclint:none", true) + (options as StandardJavadocDocletOptions).addBooleanOption("Xdoclint:-missing", true) +} + +jacoco { + toolVersion = project.libs.versions.jacoco.get() +} + +tasks.jacocoTestReport { + reports { + xml.required.set(true) + xml.outputLocation.set(layout.buildDirectory.file("reports/jacoco/report.xml")) + csv.required.set(false) + html.required.set(true) + html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco/html")) + } + dependsOn(tasks.test) + finalizedBy(tasks.getByName("jacocoTestCoverageVerification")) +} + +tasks.withType().configureEach { + inputs.file(layout.buildDirectory.file("reports/jacoco/report.xml")) + outputs.file(layout.buildDirectory.file("reports/jacoco/jacocoTestCoverageVerification")) + + violationRules { + rule { + limit { + counter = "LINE" + value = "COVEREDRATIO" + minimum = BigDecimal.valueOf(0.8) + } + limit { + counter = "BRANCH" + value = "COVEREDRATIO" + minimum = BigDecimal.valueOf(0.8) + } + excludes = listOf() + } + rule { + element = "CLASS" + limit { + counter = "LINE" + value = "COVEREDRATIO" + minimum = BigDecimal.valueOf(0.5) + } + limit { + counter = "BRANCH" + value = "COVEREDRATIO" + minimum = BigDecimal.valueOf(0.5) + } + excludes = mutableListOf( + "com.github.nagyesta.cacheonly.raw.BatchServiceCaller", + "com.github.nagyesta.cacheonly.transform.NoOpPartialCacheSupport" + ) + } + } + doLast { + layout.buildDirectory.file("reports/jacoco/jacocoTestCoverageVerification").get().asFile.writeText("Passed") + } +} + +tasks.jar.configure { + dependsOn(tasks.check) +} + +tasks.withType().configureEach { + configProperties = mutableMapOf( + "base_dir" to rootDir.absolutePath.toString(), + "cache_file" to layout.buildDirectory.file("checkstyle/cacheFile").get().asFile.absolutePath.toString() + ) + checkstyle.toolVersion = project.libs.versions.checkstyle.get() + checkstyle.configFile = project.file("config/checkstyle/checkstyle.xml") + reports { + xml.required.set(false) + html.required.set(true) + html.stylesheet = project.resources.text.fromFile("config/checkstyle/checkstyle-stylesheet.xsl") + } +} + +//Disable metadata publishing and rely on Maven only +tasks.withType().configureEach { + enabled = false +} + +ossIndexAudit { + username = project.extra.get("ossIndexUser").toString() + password = project.extra.get("ossIndexPass").toString() + isPrintBanner = false + isColorEnabled = true + isShowAll = false + outputFormat = OutputFormat.DEFAULT + @Suppress("UNCHECKED_CAST") + excludeVulnerabilityIds = project.extra.get("ossIndexExclusions") as MutableSet +} + +tasks.cyclonedxBom { + setProjectType("library") + setIncludeConfigs(listOf("runtimeClasspath")) + setSkipConfigs(listOf("compileClasspath", "testCompileClasspath")) + setSkipProjects(listOf()) + setSchemaVersion("1.5") + setDestination(file("build/reports")) + setOutputName("bom") + setOutputFormat("json") + //noinspection UnnecessaryQualifiedReference + val attachmentText = org.cyclonedx.model.AttachmentText() + attachmentText.text = Base64.getEncoder().encodeToString( + file("${project.project.projectDir}/LICENSE").readBytes() + ) + attachmentText.encoding = "base64" + attachmentText.contentType = "text/plain" + //noinspection UnnecessaryQualifiedReference + val license = org.cyclonedx.model.License() + license.name = "MIT License" + license.setLicenseText(attachmentText) + license.url = "https://raw.githubusercontent.com/nagyesta/cache-only/main/LICENSE" + setLicenseChoice { + it.addLicense(license) + } +} + +checkstyle { + toolVersion = project.libs.versions.checkstyle.get() +} + +nexusPublishing { + repositories { + sonatype { + username = project.extra.get("ossrhUser").toString() + password = project.extra.get("ossrhPass").toString() + } + } +} + +publishing { + repositories { + maven { + name = "GitHubPackages" + url = uri(project.extra.get("githubMavenRepoUrl").toString()) + credentials { + username = project.extra.get("gitUser").toString() + password = project.extra.get("gitToken").toString() + } + } + } + publications { + create("mavenJava") { + from(components["java"]) + artifactId = project.name + pom { + name.set(project.extra.get("artifactDisplayName").toString()) + description.set(project.extra.get("artifactDescription").toString()) + url.set(project.extra.get("repoUrl").toString()) + packaging = "jar" + licenses { + license { + name.set(project.extra.get("licenseName").toString()) + url.set(project.extra.get("licenseUrl").toString()) + } + } + developers { + developer { + id.set(project.extra.get("maintainerId").toString()) + name.set(project.extra.get("maintainerName").toString()) + email.set(project.extra.get("maintainerUrl").toString()) + } + } + scm { + connection.set(project.extra.get("scmConnection").toString()) + developerConnection.set(project.extra.get("scmConnection").toString()) + url.set(project.extra.get("scmProjectUrl").toString()) + } + } + pom.withXml { + asNode().apply { + (get("dependencies") as NodeList).forEach { depsNode -> + ((depsNode as Node).get("dependency") as NodeList).forEach { depNode -> + ((depNode as Node).get("scope") as NodeList).forEach { scope -> + if (scope is Node && "runtime" == scope.text()) { + scope.setValue("compile") + } + } + } + } + } + } + } + } +} + +signing { + sign(publishing.publications["mavenJava"]) +} diff --git a/config/ossindex/ossIndexAudit.gradle b/config/ossindex/ossIndexAudit.gradle deleted file mode 100644 index bb25bd9..0000000 --- a/config/ossindex/ossIndexAudit.gradle +++ /dev/null @@ -1,10 +0,0 @@ -def readExclusions() { - return rootProject.file("config/ossindex/exclusions.txt").readLines() - .stream() - .filter(s -> !s.isBlank()) - .toArray() -} - -project.ext { - ossIndexExclusions = readExclusions() -} diff --git a/config/ossindex/ossIndexAudit.gradle.kts b/config/ossindex/ossIndexAudit.gradle.kts new file mode 100644 index 0000000..f855baa --- /dev/null +++ b/config/ossindex/ossIndexAudit.gradle.kts @@ -0,0 +1,11 @@ +buildscript { + fun readExclusions(): MutableSet { + return rootProject.file("config/ossindex/exclusions.txt").readLines() + .stream() + .toList() + .filter { it.isNotBlank() } + .toMutableSet() + } + + extra.set("ossIndexExclusions", readExclusions()) +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b99007c..d2c6b01 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -slf4j = "2.0.16" +slf4j = "2.0.17" logback = "1.5.17" spring = "6.2.3" commonsCollections = "4.4" @@ -13,8 +13,8 @@ gitVersionerPlugin = "1.6.7" indexScanPlugin = "3.0.0" owaspPlugin = "12.1.0" -checkstyle = "10.12.2" -jacoco = "0.8.10" +checkstyle = "10.21.4" +jacoco = "0.8.12" cycloneDxBomPlugin = "2.2.0" licenseePlugin = "1.12.0" nexusPublishPlugin = "2.0.0" @@ -29,6 +29,10 @@ jupiter-core = { module = "org.junit.jupiter:junit-jupiter", version.ref = "jupi mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" } jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotation" } +# used by Renovate +checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } +# used by Renovate +jacoco = { module = "org.jacoco:org.jacoco.core", version.ref = "jacoco" } [plugins] lombok = { id = "io.freefair.lombok", version.ref = "lombokPlugin" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e475e82..bc297c6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -36,14 +36,6 @@ - - - - - - - - @@ -60,14 +52,6 @@ - - - - - - - - @@ -81,11 +65,6 @@ - - - - - @@ -316,11 +295,6 @@ - - - - - @@ -365,18 +339,7 @@ - - - - - - - - - - - @@ -400,9 +363,6 @@ - - - @@ -415,14 +375,6 @@ - - - - - - - - @@ -433,11 +385,6 @@ - - - - - @@ -470,9 +417,6 @@ - - - @@ -564,12 +508,12 @@ - - - + + + - - + + @@ -614,6 +558,14 @@ + + + + + + + + @@ -746,22 +698,12 @@ - - - - - - - - - - - + + + - - - - + + @@ -769,16 +711,6 @@ - - - - - - - - - - @@ -799,11 +731,6 @@ - - - - - @@ -893,14 +820,6 @@ - - - - - - - - @@ -953,12 +872,12 @@ - - - + + + - - + + @@ -969,9 +888,9 @@ - - - + + + @@ -979,12 +898,12 @@ - - - + + + - - + + @@ -1208,6 +1127,11 @@ + + + + + @@ -1330,14 +1254,6 @@ - - - - - - - - @@ -1351,11 +1267,6 @@ - - - - - @@ -1369,14 +1280,6 @@ - - - - - - - - @@ -1393,14 +1296,6 @@ - - - - - - - - @@ -1414,16 +1309,6 @@ - - - - - - - - - - @@ -1754,16 +1639,16 @@ - - - - - + + + + + @@ -1903,21 +1788,11 @@ - - - - - - - - - - @@ -2011,41 +1886,41 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + @@ -2069,12 +1944,12 @@ - - - + + + - - + + @@ -2238,84 +2113,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2360,6 +2192,14 @@ + + + + + + + + @@ -2368,9 +2208,9 @@ - - - + + + @@ -2381,6 +2221,14 @@ + + + + + + + + @@ -2394,6 +2242,14 @@ + + + + + + + + @@ -2402,14 +2258,6 @@ - - - - - - - - @@ -2418,34 +2266,16 @@ - - - - - - - - - - - - - - - - - - @@ -2454,11 +2284,6 @@ - - - - - @@ -2783,12 +2608,12 @@ - - - + + + - - + + diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 890d238..0000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'cache-only' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..b737664 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "cache-only" diff --git a/src/main/java/com/github/nagyesta/cacheonly/core/AbstractCacheServiceTemplate.java b/src/main/java/com/github/nagyesta/cacheonly/core/AbstractCacheServiceTemplate.java index eff25a3..34207a7 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/core/AbstractCacheServiceTemplate.java +++ b/src/main/java/com/github/nagyesta/cacheonly/core/AbstractCacheServiceTemplate.java @@ -16,13 +16,7 @@ import org.slf4j.LoggerFactory; import org.springframework.util.Assert; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -36,7 +30,7 @@ * @param The type of the partial request. * @param The type of the partial response. * @param The type of the cache key. - * @param The type of the Id which allows unique association of partial request + * @param The type of the ID which allows unique association of partial request * and partial response pairs in the scope of the batch. */ public abstract class AbstractCacheServiceTemplate, @@ -63,9 +57,10 @@ public AbstractCacheServiceTemplate( @Nullable @Override - public BS callCacheableBatchService(final @NotNull BR request) throws BatchServiceException { - final long start = System.currentTimeMillis(); - Map requestMap = batchRequestTransformer.splitToPartialRequest(request); + public BS callCacheableBatchService( + final @NotNull BR request) throws BatchServiceException { + final var start = System.currentTimeMillis(); + var requestMap = batchRequestTransformer.splitToPartialRequest(request); try { logger.info("Processing batch of {} partial requests.", requestMap.size()); logger.trace("Processing batch of partial requests with ids: {}", requestMap.keySet()); @@ -82,16 +77,17 @@ public BS callCacheableBatchService(final @NotNull BR request) throws BatchServi fromCache.putAll(fetchAllFromOriginService(requestMap)); return batchResponseTransformer.mergeToBatchResponse(fromCache); } finally { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().debug("Total execution completed under {} ms.", end - start); } } @Nullable @Override - public BS callBatchServiceAndPutAllToCache(final @NotNull BR request) throws BatchServiceException { - final Map requestMap = batchRequestTransformer.splitToPartialRequest(request); - final Map response = fetchAllFromOriginService(requestMap); + public BS callBatchServiceAndPutAllToCache( + final @NotNull BR request) throws BatchServiceException { + final var requestMap = batchRequestTransformer.splitToPartialRequest(request); + final var response = fetchAllFromOriginService(requestMap); return batchResponseTransformer.mergeToBatchResponse(response); } @@ -103,12 +99,13 @@ public BS callBatchServiceAndPutAllToCache(final @NotNull BR request) throws Bat * @throws BatchServiceException When the resolution failed. */ @NotNull - protected Map fetchAllFromOriginService(final @NotNull Map requestMap) throws BatchServiceException { + protected Map fetchAllFromOriginService( + final @NotNull Map requestMap) throws BatchServiceException { final Map response; if (requestMap.isEmpty()) { response = Collections.emptyMap(); } else { - final List> partitions = partitionOriginRequests(requestMap); + final var partitions = partitionOriginRequests(requestMap); metricsCollector.partitionsCreated(partitions.size()); try { response = callOriginWithPartitions(partitions); @@ -129,19 +126,21 @@ protected Map fetchAllFromOriginService(final @NotNull Map request * @throws BatchServiceException When the origin call failed. */ @NotNull - protected abstract Map callOriginWithPartitions(@NotNull List> requestPartitions) throws BatchServiceException; + protected abstract Map callOriginWithPartitions( + @NotNull List> requestPartitions) throws BatchServiceException; /** * Evaluates whether the refresh strategy allows us to put to the cache and performs - * a put with all of the responses if it is allowed. + * a put with all the responses if it is allowed. * * @param strategy The refresh strategy. * @param request The request we need to use to find the cache keys when we put items into the cache. * @param response The response we need to put into the cache. */ - protected void populateCacheWithResponse(final @NotNull CacheRefreshStrategy strategy, - final @NotNull Map request, - final @NotNull Map response) { + protected void populateCacheWithResponse( + final @NotNull CacheRefreshStrategy strategy, + final @NotNull Map request, + final @NotNull Map response) { if (strategy.allowsCachePut()) { logger.trace("Responses passed for cache PUT with ids: {}", response.keySet()); logger.trace("Requests passed for cache PUT with ids: {}", request.keySet()); @@ -158,8 +157,8 @@ protected void populateCacheWithResponse(final @NotNull CacheRefreshStrategy str @NotNull private List> partitionOriginRequests(final @NotNull Map requestMap) { - final ArrayList keyList = new ArrayList<>(requestMap.keySet()); - final List> partitions = ListUtils.partition(keyList, batchServiceCaller.maxPartitionSize()); + final var keyList = new ArrayList<>(requestMap.keySet()); + final var partitions = ListUtils.partition(keyList, batchServiceCaller.maxPartitionSize()); logger.debug("Created {} partitions.", partitions.size()); return partitions.stream() .map(p -> p.stream().collect(Collectors.toMap(Function.identity(), requestMap::get))) @@ -167,8 +166,10 @@ private List> partitionOriginRequests(final @NotNull Map reque } @NotNull - private Map selectRemainingKeysToFetchFromOrigin(final @NotNull Map requestMap, final Map fromCache) { - final Set toBeFetched = batchServiceCaller.refreshStrategy() + private Map selectRemainingKeysToFetchFromOrigin( + final @NotNull Map requestMap, + final Map fromCache) { + final var toBeFetched = batchServiceCaller.refreshStrategy() .selectItemsForFetch(requestMap.keySet(), fromCache.keySet(), batchServiceCaller.maxPartitionSize()); logger.trace("Fetch will be performed for ids: {}", toBeFetched); logger.debug("Fetch will be performed for {} items.", toBeFetched.size()); @@ -177,8 +178,10 @@ private Map selectRemainingKeysToFetchFromOrigin(final @NotNull Map attemptFetchingFromCache(final @NotNull Map requestMap, - final @NotNull CacheRefreshStrategy strategy) throws CacheMissException { + private Map attemptFetchingFromCache( + final @NotNull Map requestMap, + final @NotNull CacheRefreshStrategy strategy) + throws CacheMissException { final Map result = new HashMap<>(); if (strategy.allowsCacheGet()) { metricsCollector.cacheGet(requestMap.size()); @@ -203,8 +206,10 @@ private Map attemptFetchingFromCache(final @NotNull Map requestMap * @throws CacheMissException When a request is not found and the strategy does not allow us to continue. */ @NotNull - protected abstract Map fetchAllFromCache(@NotNull CacheRefreshStrategy strategy, - @NotNull Map requestMap) throws CacheMissException; + protected abstract Map fetchAllFromCache( + @NotNull CacheRefreshStrategy strategy, + @NotNull Map requestMap) + throws CacheMissException; /** * Attempts to fetch a single entry from cache. @@ -215,13 +220,15 @@ protected abstract Map fetchAllFromCache(@NotNull CacheRefreshStrategy st * @throws CacheMissException When the request is not found and the strategy does not allow us to continue. */ @NotNull - protected Optional fetchOneFromCache(final @NotNull CacheRefreshStrategy strategy, - final @NotNull PR request) throws CacheMissException { - final Optional> key = Optional.ofNullable(partialCacheSupport.toCacheKey(request)); - final Optional fromCache = key.map(partialCacheSupport::getFromCache); - if (!fromCache.isPresent()) { + protected Optional fetchOneFromCache( + final @NotNull CacheRefreshStrategy strategy, + final @NotNull PR request) + throws CacheMissException { + final var key = Optional.ofNullable(partialCacheSupport.toCacheKey(request)); + final var fromCache = key.map(partialCacheSupport::getFromCache); + if (fromCache.isEmpty()) { if (strategy.shouldFailOnMiss()) { - throw new CacheMissException("Item with id not found in cache: " + key.map(CacheKey::getId).orElse(null)); + throw new CacheMissException("Item with id not found in cache: " + key.map(CacheKey::id).orElse(null)); } key.ifPresent(k -> logger.trace("Cache miss observed for key: {}", k)); } @@ -238,8 +245,10 @@ protected Optional fetchOneFromCache(final @NotNull CacheRefreshStrategy str * @throws BatchServiceException When the origin call fails. */ @NotNull - protected Map fetchSinglePartitionFromOrigin(final @NotNull Map requestMap, - final @NotNull CacheRefreshStrategy strategy) throws BatchServiceException { + protected Map fetchSinglePartitionFromOrigin( + final @NotNull Map requestMap, + final @NotNull CacheRefreshStrategy strategy) + throws BatchServiceException { final Map response = new HashMap<>(doFetchFromOrigin(requestMap)); logger().trace("Responses fetched for ids: {}", response.keySet()); logger().debug("Responses fetched for {} items.", response.size()); @@ -248,11 +257,13 @@ protected Map fetchSinglePartitionFromOrigin(final @NotNull Map re } @NotNull - private Map doFetchFromOrigin(final @NotNull Map requestMap) throws BatchServiceException { - final Optional
batchRequest = Optional.ofNullable(batchRequestTransformer().mergeToBatchRequest(requestMap)); + private Map doFetchFromOrigin( + final @NotNull Map requestMap) + throws BatchServiceException { + final var batchRequest = Optional.ofNullable(batchRequestTransformer().mergeToBatchRequest(requestMap)); Map response = Collections.emptyMap(); if (batchRequest.isPresent()) { - final Optional listResponse = Optional.ofNullable(batchServiceCaller().callBatchService(batchRequest.get())); + final var listResponse = Optional.ofNullable(batchServiceCaller().callBatchService(batchRequest.get())); response = listResponse.map(batchResponseTransformer()::splitToPartialResponse).orElse(Collections.emptyMap()); } return response; @@ -278,7 +289,8 @@ protected final Logger logger() { return logger; } - public final void setMetricsCollector(final BatchServiceCallMetricCollector metricsCollector) { + public final void setMetricsCollector( + final BatchServiceCallMetricCollector metricsCollector) { this.metricsCollector = metricsCollector; } } diff --git a/src/main/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategy.java b/src/main/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategy.java index 0449ce4..e126905 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategy.java +++ b/src/main/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategy.java @@ -4,11 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.springframework.util.Assert; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * Defines the supported strategies used for refreshing the cache using batch calls. @@ -22,9 +18,10 @@ public enum CacheRefreshStrategy { CACHE_ONLY { @NotNull @Override - public Set selectItemsForFetch(final @NotNull Set allRequestIds, - final @NotNull Set idsFoundInCache, - final int maxPartitionSize) { + public Set selectItemsForFetch( + final @NotNull Set allRequestIds, + final @NotNull Set idsFoundInCache, + final int maxPartitionSize) { assertInputIsValid(allRequestIds, idsFoundInCache, maxPartitionSize); return Collections.emptySet(); } @@ -42,13 +39,14 @@ public Set selectItemsForFetch(final @NotNull Set allRequestIds, OPPORTUNISTIC { @NotNull @Override - public Set selectItemsForFetch(final @NotNull Set allRequestIds, - final @NotNull Set idsFoundInCache, - final int maxPartitionSize) { + public Set selectItemsForFetch( + final @NotNull Set allRequestIds, + final @NotNull Set idsFoundInCache, + final int maxPartitionSize) { assertInputIsValid(allRequestIds, idsFoundInCache, maxPartitionSize); final Set result = new HashSet<>(SetUtils.difference(allRequestIds, idsFoundInCache)); - if (result.size() > 0) { - final int mustBeInLastPartition = result.size() % maxPartitionSize; + if (!result.isEmpty()) { + final var mustBeInLastPartition = result.size() % maxPartitionSize; final List fetchExtra = new ArrayList<>(idsFoundInCache); Collections.shuffle(fetchExtra); fetchExtra.stream() @@ -60,7 +58,7 @@ public Set selectItemsForFetch(final @NotNull Set allRequestIds, }, /** * If any of the items were not found in the cache, it won't even try the rest of the - * cached items and will call the real service for all of the items. This can reduce + * cached items and will call the real service for all the items. This can reduce * the overhead spent on caching when we know cache miss occurrences are likely signaling * a larger number of items missing. */ @@ -72,9 +70,10 @@ public boolean shouldFailOnMiss() { @NotNull @Override - public Set selectItemsForFetch(final @NotNull Set allRequestIds, - final @NotNull Set idsFoundInCache, - final int maxPartitionSize) { + public Set selectItemsForFetch( + final @NotNull Set allRequestIds, + final @NotNull Set idsFoundInCache, + final int maxPartitionSize) { assertInputIsValid(allRequestIds, idsFoundInCache, maxPartitionSize); Set result = SetUtils.difference(allRequestIds, idsFoundInCache); if (!result.isEmpty()) { @@ -129,27 +128,29 @@ public boolean allowsCachePut() { } /** - * Filters the set of request Ids considering the Ids found in the cache and the maximum + * Filters the set of request IDs considering the IDs found in the cache and the maximum * partition size. depending on the current strategy, we can decide to keep all or none - * of the request Ids selected for fetching (or anything in between these two extremes). + * of the request IDs selected for fetching (or anything in between these two extremes). * - * @param allRequestIds The set of all partial request Ids in the batch. - * @param idsFoundInCache The set of all partial request Ids we have found in cache. + * @param allRequestIds The set of all partial request IDs in the batch. + * @param idsFoundInCache The set of all partial request IDs we have found in cache. * @param maxPartitionSize The maximum partition size we can use in a single batch. * @param The type of the request Id. - * @return The set of request Ids we want to fetch. + * @return The set of request IDs we want to fetch. */ @NotNull - public Set selectItemsForFetch(final @NotNull Set allRequestIds, - final @NotNull Set idsFoundInCache, - final int maxPartitionSize) { + public Set selectItemsForFetch( + final @NotNull Set allRequestIds, + final @NotNull Set idsFoundInCache, + final int maxPartitionSize) { assertInputIsValid(allRequestIds, idsFoundInCache, maxPartitionSize); return SetUtils.difference(allRequestIds, idsFoundInCache); } - protected void assertInputIsValid(final @NotNull Set allRequestIds, - final @NotNull Set idsFoundInCache, - final int maxPartitionSize) { + protected void assertInputIsValid( + final @NotNull Set allRequestIds, + final @NotNull Set idsFoundInCache, + final int maxPartitionSize) { Assert.notNull(allRequestIds, "AllRequestIds cannot be null."); Assert.noNullElements(allRequestIds.toArray(), "AllRequestIds cannot contain null."); Assert.notNull(idsFoundInCache, "IdsFoundInCache cannot be null."); diff --git a/src/main/java/com/github/nagyesta/cacheonly/core/CachingServiceTemplate.java b/src/main/java/com/github/nagyesta/cacheonly/core/CachingServiceTemplate.java index 5d91ba8..999b3ab 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/core/CachingServiceTemplate.java +++ b/src/main/java/com/github/nagyesta/cacheonly/core/CachingServiceTemplate.java @@ -26,7 +26,7 @@ public interface CachingServiceTemplate { /** * Processes the provided batch request and returns an appropriate batch response. - * Does not read from cache but puts all of the returned partial responses into it. + * Does not read from cache but puts all the returned partial responses into it. * Can be ideal for background cache warm-ups. * * @param request The batch request we need to process. diff --git a/src/main/java/com/github/nagyesta/cacheonly/core/DefaultCacheServiceTemplate.java b/src/main/java/com/github/nagyesta/cacheonly/core/DefaultCacheServiceTemplate.java index 2c24123..41be1c8 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/core/DefaultCacheServiceTemplate.java +++ b/src/main/java/com/github/nagyesta/cacheonly/core/DefaultCacheServiceTemplate.java @@ -20,57 +20,62 @@ * @param The type of the partial request. * @param The type of the partial response. * @param The type of the cache key. - * @param The type of the Id which allows unique association of partial request + * @param The type of the ID which allows unique association of partial request * and partial response pairs in the scope of the batch. */ public class DefaultCacheServiceTemplate extends AbstractCacheServiceTemplate, PartialCacheSupport, BR, BS, PR, PS, C, I> { /** - * Creates a new instance and injects all of the dependencies which are necessary for it to work. + * Creates a new instance and injects all the dependencies which are necessary for it to work. * * @param partialCacheSupport The component defining how caching should work for a partial request. * @param batchRequestTransformer The component handling transformations between batch and partial requests. * @param batchResponseTransformer The component handling transformations between batch and partial responses. * @param batchServiceCaller The wrapper which is calling the real batch service in case of cache miss. */ - public DefaultCacheServiceTemplate(final @NotNull PartialCacheSupport partialCacheSupport, - final @NotNull BatchRequestTransformer batchRequestTransformer, - final @NotNull BatchResponseTransformer batchResponseTransformer, - final @NotNull BatchServiceCaller batchServiceCaller) { + public DefaultCacheServiceTemplate( + final @NotNull PartialCacheSupport partialCacheSupport, + final @NotNull BatchRequestTransformer batchRequestTransformer, + final @NotNull BatchResponseTransformer batchResponseTransformer, + final @NotNull BatchServiceCaller batchServiceCaller) { super(partialCacheSupport, batchRequestTransformer, batchResponseTransformer, batchServiceCaller); } @NotNull @Override - protected Map fetchAllFromCache(final @NotNull CacheRefreshStrategy strategy, - final @NotNull Map requestMap) throws CacheMissException { - final long start = System.currentTimeMillis(); + protected Map fetchAllFromCache( + final @NotNull CacheRefreshStrategy strategy, + final @NotNull Map requestMap) + throws CacheMissException { + final var start = System.currentTimeMillis(); final Map result = new HashMap<>(); try { - for (final Map.Entry entry : requestMap.entrySet()) { + for (final var entry : requestMap.entrySet()) { fetchOneFromCache(strategy, entry.getValue()) .ifPresent(v -> result.put(entry.getKey(), v)); } return result; } finally { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().debug("Fetch all from cache completed under {} ms.", end - start); } } @Override @NotNull - protected Map callOriginWithPartitions(final @NotNull List> requestPartitions) throws BatchServiceException { - final long start = System.currentTimeMillis(); + protected Map callOriginWithPartitions( + final @NotNull List> requestPartitions) + throws BatchServiceException { + final var start = System.currentTimeMillis(); final Map response = new HashMap<>(); try { - for (final Map partitionedMap : requestPartitions) { + for (final var partitionedMap : requestPartitions) { response.putAll(fetchSinglePartitionFromOrigin(partitionedMap, batchServiceCaller().refreshStrategy())); } return response; } finally { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().debug("Fetch all from origin completed under {} ms.", end - start); } } diff --git a/src/main/java/com/github/nagyesta/cacheonly/core/conurrent/ConcurrentCacheServiceTemplate.java b/src/main/java/com/github/nagyesta/cacheonly/core/conurrent/ConcurrentCacheServiceTemplate.java index a125b4e..92017db 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/core/conurrent/ConcurrentCacheServiceTemplate.java +++ b/src/main/java/com/github/nagyesta/cacheonly/core/conurrent/ConcurrentCacheServiceTemplate.java @@ -12,11 +12,7 @@ import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -29,7 +25,7 @@ * @param The type of the partial request. * @param The type of the partial response. * @param The type of the cache key. - * @param The type of the Id which allows unique association of partial request + * @param The type of the ID which allows unique association of partial request * and partial response pairs in the scope of the batch. */ public class ConcurrentCacheServiceTemplate @@ -41,7 +37,7 @@ public class ConcurrentCacheServiceTemplate private final ForkJoinPool originPool; /** - * Creates a new instance and injects all of the dependencies which are necessary for it to work. + * Creates a new instance and injects all the dependencies which are necessary for it to work. * * @param partialCacheSupport The component defining how caching should work for a partial request. * @param batchRequestTransformer The component handling transformations between batch and partial requests. @@ -60,9 +56,11 @@ public ConcurrentCacheServiceTemplate( @NotNull @Override - protected Map fetchAllFromCache(final @NotNull CacheRefreshStrategy strategy, - final @NotNull Map requestMap) throws CacheMissException { - final long start = System.currentTimeMillis(); + protected Map fetchAllFromCache( + final @NotNull CacheRefreshStrategy strategy, + final @NotNull Map requestMap) + throws CacheMissException { + final var start = System.currentTimeMillis(); final Map result = new ConcurrentHashMap<>(); try { callCacheParallel(strategy, requestMap, result::put); @@ -75,11 +73,11 @@ protected Map fetchAllFromCache(final @NotNull CacheRefreshStrategy strat result.clear(); } } catch (final InterruptedException | TimeoutException e) { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().warn("Cache call stopped after {} (timeout set to {}).", (end - start), partialCacheSupport().timeoutMillis(), e); result.clear(); } finally { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().debug("Fetch all from cache completed under {} ms.", end - start); } return result; @@ -87,9 +85,10 @@ protected Map fetchAllFromCache(final @NotNull CacheRefreshStrategy strat @NotNull @Override - protected Map callOriginWithPartitions(final @NotNull List> requestPartitions) + protected Map callOriginWithPartitions( + final @NotNull List> requestPartitions) throws BatchServiceException { - final long start = System.currentTimeMillis(); + final var start = System.currentTimeMillis(); final Map response = new ConcurrentHashMap<>(); try { callOriginParallel(requestPartitions, response::putAll); @@ -97,19 +96,20 @@ protected Map callOriginWithPartitions(final @NotNull List> re logger().error(e.getCause().getMessage(), e.getCause()); throw new BatchServiceException(e.getCause().getMessage(), e.getCause()); } catch (final InterruptedException | TimeoutException e) { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().warn("Origin call stopped after {} ms (timeout set to {}).", (end - start), batchServiceCaller().timeoutMillis(), e); throw new BatchServiceException("Origin call timed out.", e); } finally { - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); logger().debug("Fetch all from origin completed under {} ms.", end - start); } return response; } - private void callCacheParallel(final @NotNull CacheRefreshStrategy strategy, - final @NotNull Map requestMap, - final @NotNull BiConsumer resultConsumer) + private void callCacheParallel( + final @NotNull CacheRefreshStrategy strategy, + final @NotNull Map requestMap, + final @NotNull BiConsumer resultConsumer) throws InterruptedException, ExecutionException, TimeoutException { cachePool .submit(() -> requestMap.entrySet() @@ -119,8 +119,9 @@ private void callCacheParallel(final @NotNull CacheRefreshStrategy strategy, .get(partialCacheSupport().timeoutMillis(), TimeUnit.MILLISECONDS); } - private void callOriginParallel(final @NotNull List> requestPartitions, - final @NotNull Consumer> responseProcessor) + private void callOriginParallel( + final @NotNull List> requestPartitions, + final @NotNull Consumer> responseProcessor) throws InterruptedException, ExecutionException, TimeoutException { originPool .submit(() -> requestPartitions diff --git a/src/main/java/com/github/nagyesta/cacheonly/entity/CacheKey.java b/src/main/java/com/github/nagyesta/cacheonly/entity/CacheKey.java index 8f84e4a..fd044e6 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/entity/CacheKey.java +++ b/src/main/java/com/github/nagyesta/cacheonly/entity/CacheKey.java @@ -1,74 +1,12 @@ package com.github.nagyesta.cacheonly.entity; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; -import java.util.StringJoiner; - /** - * Represents a cache key and the Id which can help us find the request / response it belongs to. + * Represents a cache key and the ID which can help us find the request / response it belongs to. * * @param The type of the cache key. - * @param The type of the Id. + * @param The type of the ID. + * @param key The key we use for the cache. + * @param id The ID of the entity. */ -public final class CacheKey { - - private final C key; - private final I id; - - /** - * Creates a new instance. - * - * @param key The cache key value. - * @param id The Id of the partial request this key belongs to. - */ - public CacheKey(final @NotNull C key, final @NotNull I id) { - this.key = key; - this.id = id; - } - - /** - * Returns the cache key value. - * - * @return key - */ - @NotNull - public C getKey() { - return key; - } - - /** - * Returns the partial request Id. - * - * @return id - */ - @NotNull - public I getId() { - return id; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (!(o instanceof CacheKey)) { - return false; - } - final CacheKey cacheKey = (CacheKey) o; - return key.equals(cacheKey.key) && id.equals(cacheKey.id); - } - - @Override - public int hashCode() { - return Objects.hash(key, id); - } - - @Override - public String toString() { - return new StringJoiner(", ", CacheKey.class.getSimpleName() + "[", "]") - .add("key=" + key) - .add("id=" + id) - .toString(); - } +public record CacheKey(C key, I id) { } diff --git a/src/main/java/com/github/nagyesta/cacheonly/raw/concurrent/AsyncBatchServiceCaller.java b/src/main/java/com/github/nagyesta/cacheonly/raw/concurrent/AsyncBatchServiceCaller.java index 99038bf..4851772 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/raw/concurrent/AsyncBatchServiceCaller.java +++ b/src/main/java/com/github/nagyesta/cacheonly/raw/concurrent/AsyncBatchServiceCaller.java @@ -9,6 +9,7 @@ * @param
The type of the batch request. * @param The type of the batch response. */ -public interface AsyncBatchServiceCaller extends BatchServiceCaller, ConcurrentOperationSupport { +public interface AsyncBatchServiceCaller + extends BatchServiceCaller, ConcurrentOperationSupport { } diff --git a/src/main/java/com/github/nagyesta/cacheonly/raw/exception/BatchServiceException.java b/src/main/java/com/github/nagyesta/cacheonly/raw/exception/BatchServiceException.java index c7172b0..417a596 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/raw/exception/BatchServiceException.java +++ b/src/main/java/com/github/nagyesta/cacheonly/raw/exception/BatchServiceException.java @@ -23,8 +23,9 @@ public BatchServiceException(final @NotNull String message) { * @param message The message detailing the failure. * @param cause The cause of the failure. */ - public BatchServiceException(final @NotNull String message, - final @NotNull Throwable cause) { + public BatchServiceException( + final @NotNull String message, + final @NotNull Throwable cause) { super(message, cause); } } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/BatchRequestTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/BatchRequestTransformer.java index 7b60fa1..a39473b 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/BatchRequestTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/BatchRequestTransformer.java @@ -10,7 +10,7 @@ * * @param The type of the batch request. * @param

The type of the partial request. - * @param The type of the Id that can identify a partial request in the scope + * @param The type of the ID that can identify a partial request in the scope * of a batch. */ public interface BatchRequestTransformer { diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/BatchResponseTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/BatchResponseTransformer.java index d43b823..1a7832b 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/BatchResponseTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/BatchResponseTransformer.java @@ -10,7 +10,7 @@ * * @param The type of the batch response. * @param

The type of the partial response. - * @param The type of the Id that can identify a partial response and pair it + * @param The type of the ID that can identify a partial response and pair it * with a partial request of a batch request we try to respond to. */ public interface BatchResponseTransformer { diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/NoOpPartialCacheSupport.java b/src/main/java/com/github/nagyesta/cacheonly/transform/NoOpPartialCacheSupport.java index 96b833c..6b48059 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/NoOpPartialCacheSupport.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/NoOpPartialCacheSupport.java @@ -37,7 +37,9 @@ public CacheKey toCacheKey(final @NotNull PR partialRequest) { } @Override - public void putToCache(final @NotNull CacheKey key, final @NotNull PS entity) { + public void putToCache( + final @NotNull CacheKey key, + final @NotNull PS entity) { //noop } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/PartialCacheSupport.java b/src/main/java/com/github/nagyesta/cacheonly/transform/PartialCacheSupport.java index e458a72..3685d99 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/PartialCacheSupport.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/PartialCacheSupport.java @@ -6,6 +6,8 @@ import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; +import java.util.Optional; + /** * Defines how a given partial request-response pair should be cached. * @@ -54,7 +56,7 @@ public interface PartialCacheSupport { * * @return The cache */ - @NotNull + @Nullable default Cache obtainCache() { return getCacheManager().getCache(cacheName()); } @@ -66,7 +68,8 @@ default Cache obtainCache() { * @param entity The entity we want to cache. */ default void putToCache(final @NotNull CacheKey key, final @NotNull PS entity) { - obtainCache().put(key.getKey(), entity); + Optional.ofNullable(obtainCache()) + .ifPresent(cache -> cache.put(key.key(), entity)); } /** @@ -77,6 +80,8 @@ default void putToCache(final @NotNull CacheKey key, final @NotNull PS ent */ @Nullable default PS getFromCache(final @NotNull CacheKey key) { - return obtainCache().get(key.getKey(), getEntityClass()); + return Optional.ofNullable(obtainCache()) + .map(cache -> cache.get(key.key(), getEntityClass())) + .orElse(null); } } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractCollectionBasedTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractCollectionBasedTransformer.java index d65b9da..a9b2791 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractCollectionBasedTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractCollectionBasedTransformer.java @@ -27,10 +27,11 @@ public class AbstractCollectionBasedTransformer, P, I> { * Creates a new instance and defines how the {@link Collection} should be collected from a {@link java.util.stream.Stream}. * * @param collectionCollector The {@link Collector} we want to use to get a batch from a stream of elements. - * @param idFunction The transformation that can determine the Id of a given partial request (or response). + * @param idFunction The transformation that can determine the ID of a given partial request (or response). */ - public AbstractCollectionBasedTransformer(final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public AbstractCollectionBasedTransformer( + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { this(collectionCollector, idFunction, false); } @@ -38,12 +39,13 @@ public AbstractCollectionBasedTransformer(final @NotNull Collector coll * Creates a new instance and defines how the {@link Collection} should be collected from a {@link java.util.stream.Stream}. * * @param collectionCollector The {@link Collector} we want to use to get a batch from a stream of elements. - * @param idFunction The transformation that can determine the Id of a given partial request (or response). + * @param idFunction The transformation that can determine the ID of a given partial request (or response). * @param nullIfEmpty Flag telling the implementation whether we want to use null in case of an empty {@link Collection}. */ - public AbstractCollectionBasedTransformer(final @NotNull Collector collectionCollector, - final @NotNull Function idFunction, - final boolean nullIfEmpty) { + public AbstractCollectionBasedTransformer( + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction, + final boolean nullIfEmpty) { this.collectionCollector = collectionCollector; this.idFunction = idFunction; this.nullIfEmpty = nullIfEmpty; diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractMapBasedTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractMapBasedTransformer.java index b319e2a..82b72bc 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractMapBasedTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractMapBasedTransformer.java @@ -10,7 +10,7 @@ /** * Abstract transformer intended to be used in cases when the batch request (or response) - * is a simple {@link Map} of the partial requests (or responses) using the Id as key. + * is a simple {@link Map} of the partial requests (or responses) using the ID as key. * * @param The {@link Map} type used for the batch. * @param

The type of the partial request (or response) payload. @@ -28,7 +28,8 @@ public class AbstractMapBasedTransformer, P, I> { * * @param mergeMapCollector The collector we want to use when we merge partials to a batch. */ - public AbstractMapBasedTransformer(final @NotNull Collector, ?, C> mergeMapCollector) { + public AbstractMapBasedTransformer( + final @NotNull Collector, ?, C> mergeMapCollector) { this(mergeMapCollector, Map.Entry::getKey, Map.Entry::getValue, false); } @@ -42,10 +43,11 @@ public AbstractMapBasedTransformer(final @NotNull Collector, ?, * an Entry to a value in the partial entry. * @param nullIfEmpty True is we need to return null in case we are merging an empty map. */ - public AbstractMapBasedTransformer(final @NotNull Collector, ?, C> mergeMapCollector, - final @NotNull Function, I> splitKeyTransformer, - final @NotNull Function, P> splitValueTransformer, - final boolean nullIfEmpty) { + public AbstractMapBasedTransformer( + final @NotNull Collector, ?, C> mergeMapCollector, + final @NotNull Function, I> splitKeyTransformer, + final @NotNull Function, P> splitValueTransformer, + final boolean nullIfEmpty) { this.mergeMapCollector = mergeMapCollector; this.splitKeyTransformer = splitKeyTransformer; this.splitValueTransformer = splitValueTransformer; diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedCollectionBasedTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedCollectionBasedTransformer.java index f5ab2da..c380fd6 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedCollectionBasedTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedCollectionBasedTransformer.java @@ -20,7 +20,7 @@ * @param The type of the batch wrapper class. * @param The type of the {@link Collection} holding the values we want to partition. * @param The type of the partial entities. - * @param The type of the Id we can use for partial entity identification. + * @param The type of the ID we can use for partial entity identification. */ public class AbstractWrappedCollectionBasedTransformer, E, I> { @@ -31,37 +31,39 @@ public class AbstractWrappedCollectionBasedTransformer idFunction; /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param instanceSupplier The {@link Supplier} we can use for getting a new empty batch instance. * @param collectionReadFunction The function that can read the collection from a batch. * @param collectionWriteBiFunction The function that can write the collection into a batch. * @param collectionCollector The collector creating a new collection from the partial entities. - * @param idFunction The function that can convert an entity to the Id identifying it. + * @param idFunction The function that can convert an entity to the ID identifying it. */ - public AbstractWrappedCollectionBasedTransformer(final @NotNull Supplier instanceSupplier, - final @NotNull Function collectionReadFunction, - final @NotNull BiFunction collectionWriteBiFunction, - final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public AbstractWrappedCollectionBasedTransformer( + final @NotNull Supplier instanceSupplier, + final @NotNull Function collectionReadFunction, + final @NotNull BiFunction collectionWriteBiFunction, + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { this(response -> cloneWrapper(response, instanceSupplier), collectionReadFunction, collectionWriteBiFunction, collectionCollector, idFunction); } /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param cloneFunction The function that can clone a batch. * @param collectionReadFunction The function that can read the collection from a batch. * @param collectionWriteBiFunction The function that can write the collection into a batch. * @param collectionCollector The collector creating a new collection from the partial entities. - * @param idFunction The function that can convert an entity to the Id identifying it. + * @param idFunction The function that can convert an entity to the ID identifying it. */ - public AbstractWrappedCollectionBasedTransformer(final @NotNull Function cloneFunction, - final @NotNull Function collectionReadFunction, - final @NotNull BiFunction collectionWriteBiFunction, - final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public AbstractWrappedCollectionBasedTransformer( + final @NotNull Function cloneFunction, + final @NotNull Function collectionReadFunction, + final @NotNull BiFunction collectionWriteBiFunction, + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { this.cloneFunction = cloneFunction; this.collectionReadFunction = collectionReadFunction; this.collectionWriteBiFunction = collectionWriteBiFunction; @@ -70,8 +72,10 @@ public AbstractWrappedCollectionBasedTransformer(final @NotNull Function c } @NotNull - private static B cloneWrapper(final @NotNull B batch, final @NotNull Supplier instanceSupplier) { - final B target = instanceSupplier.get(); + private static B cloneWrapper( + final @NotNull B batch, + final @NotNull Supplier instanceSupplier) { + final var target = instanceSupplier.get(); BeanUtils.copyProperties(batch, target); return target; } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedMapBasedTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedMapBasedTransformer.java index 00dffe4..8fd9fb0 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedMapBasedTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/AbstractWrappedMapBasedTransformer.java @@ -20,7 +20,7 @@ * @param The type of the batch wrapper class. * @param The type of the {@link Map} holding the values we want to partition. * @param The type of the partial entities. - * @param The type of the Id we can use for partial entity identification. + * @param The type of the ID we can use for partial entity identification. */ public abstract class AbstractWrappedMapBasedTransformer, E, I> { @@ -30,32 +30,34 @@ public abstract class AbstractWrappedMapBasedTransformer, private final Collector, ?, C> mapCollector; /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param instanceSupplier The {@link Supplier} we can use for getting a new empty batch instance. * @param mapReadFunction The function that can read the map from a batch. * @param mapWriteBiFunction The function that can write the map into a batch. * @param mapCollector The collector creating a new map from the partial entities. */ - public AbstractWrappedMapBasedTransformer(final @NotNull Supplier instanceSupplier, - final @NotNull Function mapReadFunction, - final @NotNull BiFunction mapWriteBiFunction, - final @NotNull Collector, ?, C> mapCollector) { + public AbstractWrappedMapBasedTransformer( + final @NotNull Supplier instanceSupplier, + final @NotNull Function mapReadFunction, + final @NotNull BiFunction mapWriteBiFunction, + final @NotNull Collector, ?, C> mapCollector) { this(request -> cloneWrapper(request, instanceSupplier), mapReadFunction, mapWriteBiFunction, mapCollector); } /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param cloneFunction The function that can clone a batch. * @param mapReadFunction The function that can read the map from a batch. * @param mapWriteBiFunction The function that can write the map into a batch. * @param mapCollector The collector creating a new map from the partial entities. */ - public AbstractWrappedMapBasedTransformer(final @NotNull Function cloneFunction, - final @NotNull Function mapReadFunction, - final @NotNull BiFunction mapWriteBiFunction, - final @NotNull Collector, ?, C> mapCollector) { + public AbstractWrappedMapBasedTransformer( + final @NotNull Function cloneFunction, + final @NotNull Function mapReadFunction, + final @NotNull BiFunction mapWriteBiFunction, + final @NotNull Collector, ?, C> mapCollector) { this.cloneFunction = cloneFunction; this.mapReadFunction = mapReadFunction; this.mapWriteBiFunction = mapWriteBiFunction; @@ -63,8 +65,10 @@ public AbstractWrappedMapBasedTransformer(final @NotNull Function cloneFun } @NotNull - private static B cloneWrapper(final @NotNull B batch, final @NotNull Supplier instanceSupplier) { - final B target = instanceSupplier.get(); + private static B cloneWrapper( + final @NotNull B batch, + final @NotNull Supplier instanceSupplier) { + final var target = instanceSupplier.get(); BeanUtils.copyProperties(batch, target); return target; } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformer.java index f1f9e5e..57a3be8 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformer.java @@ -25,10 +25,11 @@ public class CollectionBasedRequestTransformer, P, I> * Creates a new instance and defines how the {@link Collection} should be collected from a {@link java.util.stream.Stream}. * * @param collectionCollector The {@link Collector} we want to use to get a batch from a stream of elements. - * @param idFunction The transformation that can determine the Id of a given partial request. + * @param idFunction The transformation that can determine the ID of a given partial request. */ - public CollectionBasedRequestTransformer(final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public CollectionBasedRequestTransformer( + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { super(collectionCollector, idFunction); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformer.java index 07846bd..0726f99 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformer.java @@ -25,10 +25,11 @@ public class CollectionBasedResponseTransformer, P, I> * Creates a new instance and defines how the {@link Collection} should be collected from a {@link java.util.stream.Stream}. * * @param collectionCollector The {@link Collector} we want to use to get a batch from a stream of elements. - * @param idFunction The transformation that can determine the Id of a given partial response. + * @param idFunction The transformation that can determine the ID of a given partial response. */ - public CollectionBasedResponseTransformer(final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public CollectionBasedResponseTransformer( + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { super(collectionCollector, idFunction); } @@ -36,12 +37,13 @@ public CollectionBasedResponseTransformer(final @NotNull Collector coll * Creates a new instance and defines how the {@link Collection} should be collected from a {@link java.util.stream.Stream}. * * @param collectionCollector The {@link Collector} we want to use to get a batch from a stream of elements. - * @param idFunction The transformation that can determine the Id of a given partial response. + * @param idFunction The transformation that can determine the ID of a given partial response. * @param nullIfEmpty Flag telling the implementation whether we want to use null in case of an empty {@link Collection}. */ - public CollectionBasedResponseTransformer(final @NotNull Collector collectionCollector, - final @NotNull Function idFunction, - final boolean nullIfEmpty) { + public CollectionBasedResponseTransformer( + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction, + final boolean nullIfEmpty) { super(collectionCollector, idFunction, nullIfEmpty); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformer.java index bd4c283..9a8f460 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformer.java @@ -12,7 +12,7 @@ /** * Abstract transformer intended to be used in cases when the batch request is a - * simple {@link Map} of the partial requests using the Id as key. + * simple {@link Map} of the partial requests using the ID as key. * * @param The {@link Map} type used for the batch. * @param

The type of the partial request payload. @@ -40,9 +40,10 @@ public MapBasedRequestTransformer(final @NotNull Supplier instanceSupplier) { * @param splitValueTransformer The Function we need to use when we split the batch for transforming * an Entry to a value in the partial request entry. */ - public MapBasedRequestTransformer(final @NotNull Collector, ?, C> mergeMapCollector, - final @NotNull Function, I> splitKeyTransformer, - final @NotNull Function, P> splitValueTransformer) { + public MapBasedRequestTransformer( + final @NotNull Collector, ?, C> mergeMapCollector, + final @NotNull Function, I> splitKeyTransformer, + final @NotNull Function, P> splitValueTransformer) { super(mergeMapCollector, splitKeyTransformer, splitValueTransformer, false); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformer.java index 4058c27..80cb1bd 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformer.java @@ -12,7 +12,7 @@ /** * Abstract transformer intended to be used in cases when the batch response is a - * simple {@link Map} of the partial responses using the Id as key. + * simple {@link Map} of the partial responses using the ID as key. * * @param The {@link Map} type used for the batch. * @param

The type of the partial response payload. @@ -40,10 +40,11 @@ public MapBasedResponseTransformer(final @NotNull Supplier instanceSupplier) * an Entry to a value in the partial response entry. * @param nullIfEmpty True is we need to return null in case we are merging an empty map. */ - public MapBasedResponseTransformer(final @NotNull Collector, ?, C> mergeMapCollector, - final @NotNull Function, I> splitKeyTransformer, - final @NotNull Function, P> splitValueTransformer, - final boolean nullIfEmpty) { + public MapBasedResponseTransformer( + final @NotNull Collector, ?, C> mergeMapCollector, + final @NotNull Function, I> splitKeyTransformer, + final @NotNull Function, P> splitValueTransformer, + final boolean nullIfEmpty) { super(mergeMapCollector, splitKeyTransformer, splitValueTransformer, nullIfEmpty); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformer.java index d5bb5d9..48f2483 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformer.java @@ -18,7 +18,7 @@ * @param The type of the batch wrapper class. * @param The type of the {@link Collection} holding the values we want to partition. * @param The type of the partial entities. - * @param The type of the Id we can use for partial entity identification. + * @param The type of the ID we can use for partial entity identification. */ public class WrappedCollectionBasedRequestTransformer, E, I> extends AbstractWrappedCollectionBasedTransformer @@ -26,36 +26,38 @@ public class WrappedCollectionBasedRequestTransformer /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param instanceSupplier The {@link Supplier} we can use for getting a new empty batch instance. * @param collectionReadFunction The function that can read the collection from a batch. * @param collectionWriteBiFunction The function that can write the collection into a batch. * @param collectionCollector The collector creating a new collection from the partial entities. - * @param idFunction The function that can convert an entity to the Id identifying it. + * @param idFunction The function that can convert an entity to the ID identifying it. */ - public WrappedCollectionBasedRequestTransformer(final @NotNull Supplier instanceSupplier, - final @NotNull Function collectionReadFunction, - final @NotNull BiFunction collectionWriteBiFunction, - final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public WrappedCollectionBasedRequestTransformer( + final @NotNull Supplier instanceSupplier, + final @NotNull Function collectionReadFunction, + final @NotNull BiFunction collectionWriteBiFunction, + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { super(instanceSupplier, collectionReadFunction, collectionWriteBiFunction, collectionCollector, idFunction); } /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param cloneFunction The function that can clone a batch. * @param collectionReadFunction The function that can read the collection from a batch. * @param collectionWriteBiFunction The function that can write the collection into a batch. * @param collectionCollector The collector creating a new collection from the partial entities. - * @param idFunction The function that can convert an entity to the Id identifying it. + * @param idFunction The function that can convert an entity to the ID identifying it. */ - public WrappedCollectionBasedRequestTransformer(final @NotNull Function cloneFunction, - final @NotNull Function collectionReadFunction, - final @NotNull BiFunction collectionWriteBiFunction, - final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public WrappedCollectionBasedRequestTransformer( + final @NotNull Function cloneFunction, + final @NotNull Function collectionReadFunction, + final @NotNull BiFunction collectionWriteBiFunction, + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { super(cloneFunction, collectionReadFunction, collectionWriteBiFunction, collectionCollector, idFunction); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformer.java index 0f23c4c..1c45c6d 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformer.java @@ -18,43 +18,45 @@ * @param The type of the batch wrapper class. * @param The type of the {@link Collection} holding the values we want to partition. * @param The type of the partial entities. - * @param The type of the Id we can use for partial entity identification. + * @param The type of the ID we can use for partial entity identification. */ public class WrappedCollectionBasedResponseTransformer, E, I> extends AbstractWrappedCollectionBasedTransformer implements BatchResponseTransformer { /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param instanceSupplier The {@link Supplier} we can use for getting a new empty batch instance. * @param collectionReadFunction The function that can read the collection from a batch. * @param collectionWriteBiFunction The function that can write the collection into a batch. * @param collectionCollector The collector creating a new collection from the partial entities. - * @param idFunction The function that can convert an entity to the Id identifying it. + * @param idFunction The function that can convert an entity to the ID identifying it. */ - public WrappedCollectionBasedResponseTransformer(final @NotNull Supplier instanceSupplier, - final @NotNull Function collectionReadFunction, - final @NotNull BiFunction collectionWriteBiFunction, - final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public WrappedCollectionBasedResponseTransformer( + final @NotNull Supplier instanceSupplier, + final @NotNull Function collectionReadFunction, + final @NotNull BiFunction collectionWriteBiFunction, + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { super(instanceSupplier, collectionReadFunction, collectionWriteBiFunction, collectionCollector, idFunction); } /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param cloneFunction The function that can clone a batch. * @param collectionReadFunction The function that can read the collection from a batch. * @param collectionWriteBiFunction The function that can write the collection into a batch. * @param collectionCollector The collector creating a new collection from the partial entities. - * @param idFunction The function that can convert an entity to the Id identifying it. + * @param idFunction The function that can convert an entity to the ID identifying it. */ - public WrappedCollectionBasedResponseTransformer(final @NotNull Function cloneFunction, - final @NotNull Function collectionReadFunction, - final @NotNull BiFunction collectionWriteBiFunction, - final @NotNull Collector collectionCollector, - final @NotNull Function idFunction) { + public WrappedCollectionBasedResponseTransformer( + final @NotNull Function cloneFunction, + final @NotNull Function collectionReadFunction, + final @NotNull BiFunction collectionWriteBiFunction, + final @NotNull Collector collectionCollector, + final @NotNull Function idFunction) { super(cloneFunction, collectionReadFunction, collectionWriteBiFunction, collectionCollector, idFunction); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformer.java index 857027e..c1f499a 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformer.java @@ -17,39 +17,41 @@ * @param The type of the batch wrapper class. * @param The type of the {@link Map} holding the values we want to partition. * @param The type of the partial entities. - * @param The type of the Id we can use for partial entity identification. + * @param The type of the ID we can use for partial entity identification. */ public class WrappedMapBasedRequestTransformer, E, I> extends AbstractWrappedMapBasedTransformer implements BatchRequestTransformer { /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param instanceSupplier The {@link Supplier} we can use for getting a new empty batch instance. * @param mapReadFunction The function that can read the map from a batch. * @param mapWriteBiFunction The function that can write the map into a batch. * @param mapCollector The collector creating a new map from the partial entities. */ - public WrappedMapBasedRequestTransformer(final @NotNull Supplier instanceSupplier, - final @NotNull Function mapReadFunction, - final @NotNull BiFunction mapWriteBiFunction, - final @NotNull Collector, ?, C> mapCollector) { + public WrappedMapBasedRequestTransformer( + final @NotNull Supplier instanceSupplier, + final @NotNull Function mapReadFunction, + final @NotNull BiFunction mapWriteBiFunction, + final @NotNull Collector, ?, C> mapCollector) { super(instanceSupplier, mapReadFunction, mapWriteBiFunction, mapCollector); } /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param cloneFunction The function that can clone a batch. * @param mapReadFunction The function that can read the map from a batch. * @param mapWriteBiFunction The function that can write the map into a batch. * @param mapCollector The collector creating a new map from the partial entities. */ - public WrappedMapBasedRequestTransformer(final @NotNull Function cloneFunction, - final @NotNull Function mapReadFunction, - final @NotNull BiFunction mapWriteBiFunction, - final @NotNull Collector, ?, C> mapCollector) { + public WrappedMapBasedRequestTransformer( + final @NotNull Function cloneFunction, + final @NotNull Function mapReadFunction, + final @NotNull BiFunction mapWriteBiFunction, + final @NotNull Collector, ?, C> mapCollector) { super(cloneFunction, mapReadFunction, mapWriteBiFunction, mapCollector); } diff --git a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformer.java b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformer.java index 12cef12..4ae083e 100644 --- a/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformer.java +++ b/src/main/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformer.java @@ -17,39 +17,41 @@ * @param The type of the batch wrapper class. * @param The type of the {@link Map} holding the values we want to partition. * @param The type of the partial entities. - * @param The type of the Id we can use for partial entity identification. + * @param The type of the ID we can use for partial entity identification. */ public class WrappedMapBasedResponseTransformer, E, I> extends AbstractWrappedMapBasedTransformer implements BatchResponseTransformer { /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param instanceSupplier The {@link Supplier} we can use for getting a new empty batch instance. * @param mapReadFunction The function that can read the map from a batch. * @param mapWriteBiFunction The function that can write the map into a batch. * @param mapCollector The collector creating a new map from the partial entities. */ - public WrappedMapBasedResponseTransformer(final @NotNull Supplier instanceSupplier, - final @NotNull Function mapReadFunction, - final @NotNull BiFunction mapWriteBiFunction, - final @NotNull Collector, ?, C> mapCollector) { + public WrappedMapBasedResponseTransformer( + final @NotNull Supplier instanceSupplier, + final @NotNull Function mapReadFunction, + final @NotNull BiFunction mapWriteBiFunction, + final @NotNull Collector, ?, C> mapCollector) { super(instanceSupplier, mapReadFunction, mapWriteBiFunction, mapCollector); } /** - * Creates a new instance and sets all of the parameters we can use for customization. + * Creates a new instance and sets all the parameters we can use for customization. * * @param cloneFunction The function that can clone a batch. * @param mapReadFunction The function that can read the map from a batch. * @param mapWriteBiFunction The function that can write the map into a batch. * @param mapCollector The collector creating a new map from the partial entities. */ - public WrappedMapBasedResponseTransformer(final @NotNull Function cloneFunction, - final @NotNull Function mapReadFunction, - final @NotNull BiFunction mapWriteBiFunction, - final @NotNull Collector, ?, C> mapCollector) { + public WrappedMapBasedResponseTransformer( + final @NotNull Function cloneFunction, + final @NotNull Function mapReadFunction, + final @NotNull BiFunction mapWriteBiFunction, + final @NotNull Collector, ?, C> mapCollector) { super(cloneFunction, mapReadFunction, mapWriteBiFunction, mapCollector); } diff --git a/src/test/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategyTest.java b/src/test/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategyTest.java index 244db60..8e61ecf 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategyTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/core/CacheRefreshStrategyTest.java @@ -5,23 +5,11 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.*; import java.util.stream.Stream; -import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.CACHE_ONLY; -import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.NEVER_CACHE; -import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.OPPORTUNISTIC; -import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.OPTIMISTIC; -import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.PESSIMISTIC; -import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.values; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static com.github.nagyesta.cacheonly.core.CacheRefreshStrategy.*; +import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.params.provider.Arguments.of; /** @@ -111,11 +99,12 @@ private static Stream invalidSelectItemProvider() { @ParameterizedTest @MethodSource("cacheUseProvider") void testAllowsCacheGetShouldReturnTheExpectedValueWhenCalled( - final CacheRefreshStrategy underTest, final boolean expected) { + final CacheRefreshStrategy underTest, + final boolean expected) { //given //when - final boolean actual = underTest.allowsCacheGet(); + final var actual = underTest.allowsCacheGet(); //then assertEquals(expected, actual); @@ -124,11 +113,12 @@ void testAllowsCacheGetShouldReturnTheExpectedValueWhenCalled( @ParameterizedTest @MethodSource("failOnMissProvider") void testShouldFailOnMissShouldReturnTheExpectedValueWhenCalled( - final CacheRefreshStrategy underTest, final boolean expected) { + final CacheRefreshStrategy underTest, + final boolean expected) { //given //when - final boolean actual = underTest.shouldFailOnMiss(); + final var actual = underTest.shouldFailOnMiss(); //then assertEquals(expected, actual); @@ -137,11 +127,12 @@ void testShouldFailOnMissShouldReturnTheExpectedValueWhenCalled( @ParameterizedTest @MethodSource("cacheUseProvider") void testAllowsCachePutShouldReturnTheExpectedValueWhenCalled( - final CacheRefreshStrategy underTest, final boolean expected) { + final CacheRefreshStrategy underTest, + final boolean expected) { //given //when - final boolean actual = underTest.allowsCachePut(); + final var actual = underTest.allowsCachePut(); //then assertEquals(expected, actual); @@ -151,12 +142,15 @@ void testAllowsCachePutShouldReturnTheExpectedValueWhenCalled( @MethodSource("validSelectItemProvider") void testSelectItemsForFetchShouldKeepTheExpectedItemsWhenCalledWithValidInput( final CacheRefreshStrategy underTest, - final Set allIds, final Set foundIds, final int partitionSize, - final SortedSet expectedMandatory, final int expectedAdditional) { + final Set allIds, + final Set foundIds, + final int partitionSize, + final SortedSet expectedMandatory, + final int expectedAdditional) { //given //when - final Set actual = underTest.selectItemsForFetch(allIds, foundIds, partitionSize); + final var actual = underTest.selectItemsForFetch(allIds, foundIds, partitionSize); //then final SortedSet common = new TreeSet<>(SetUtils.intersection(actual, expectedMandatory)); @@ -171,7 +165,9 @@ void testSelectItemsForFetchShouldKeepTheExpectedItemsWhenCalledWithValidInput( @MethodSource("invalidSelectItemProvider") void testSelectItemsForFetchShouldThrowExceptionWhenCalledWithInvalidInput( final CacheRefreshStrategy underTest, - final Set allIds, final Set foundIds, final int partitionSize) { + final Set allIds, + final Set foundIds, + final int partitionSize) { //given //when diff --git a/src/test/java/com/github/nagyesta/cacheonly/core/CommentCacheServiceTemplateIntegrationTest.java b/src/test/java/com/github/nagyesta/cacheonly/core/CommentCacheServiceTemplateIntegrationTest.java index 51fcd2b..370caaf 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/core/CommentCacheServiceTemplateIntegrationTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/core/CommentCacheServiceTemplateIntegrationTest.java @@ -10,33 +10,18 @@ import com.github.nagyesta.cacheonly.raw.exception.BatchServiceException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InOrder; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.UUID; +import java.util.*; import static com.github.nagyesta.cacheonly.example.replies.CommentContext.THREADS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = CommentContext.class) @@ -57,7 +42,7 @@ class CommentCacheServiceTemplateIntegrationTest { void testCallCacheableBatchServiceShouldWrapExceptionWhenExceptionCaught() { //given // create the test request - final ThreadRequest request = ThreadRequest.builder() + final var request = ThreadRequest.builder() .articleId(UUID.randomUUID()) .threadIds(Collections.singletonList(1L)) .build(); @@ -70,25 +55,26 @@ void testCallCacheableBatchServiceShouldWrapExceptionWhenExceptionCaught() { @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldNotPutAnythingWhenNoResultsFound() throws BatchServiceException { + void testCallCacheableBatchServiceShouldNotPutAnythingWhenNoResultsFound() + throws BatchServiceException { //given // create the test request - final List threadIds = Arrays.asList(1L, 2L, 3L, 4L); - final ThreadRequest request = ThreadRequest.builder() + final var threadIds = Arrays.asList(1L, 2L, 3L, 4L); + final var request = ThreadRequest.builder() .articleId(CommentService.NO_COMMENT) .threadIds(threadIds) .build(); //when - final CommentThreads actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNull(actual); // all items were tried from the cache and missed - final Cache cache = cacheManager.getCache(THREADS); - final InOrder inOrder = Mockito.inOrder(cache); + final var cache = cacheManager.getCache(THREADS); + final var inOrder = Mockito.inOrder(cache); threadIds.forEach(id -> inOrder.verify(cache).get( - eq(CommentService.NO_COMMENT.toString() + "_thread_" + id), + eq(CommentService.NO_COMMENT + "_thread_" + id), eq(CommentThreads.class))); // nothing is put into the cache as all of them are missed inOrder.verify(cache, never()).put(anyString(), any()); @@ -96,107 +82,110 @@ void testCallCacheableBatchServiceShouldNotPutAnythingWhenNoResultsFound() throw @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldCacheWhenResultsAreFound() throws BatchServiceException, NotFoundException { + void testCallCacheableBatchServiceShouldCacheWhenResultsAreFound() + throws BatchServiceException, NotFoundException { //given // create the test request - final List threadIds = Arrays.asList(1L, 2L, 3L, 4L); - final ThreadRequest request = ThreadRequest.builder() + final var threadIds = Arrays.asList(1L, 2L, 3L, 4L); + final var request = ThreadRequest.builder() .articleId(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT) .threadIds(threadIds) .build(); - final CommentThreads expected = commentService.threadsOf(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT, new HashSet<>(threadIds)); + final var expected = commentService.threadsOf(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT, new HashSet<>(threadIds)); //when - final CommentThreads actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); assertEquals(2, actual.getThreads().size()); assertEquals(expected, actual); // all items were tried from the cache and missed - final Cache cache = cacheManager.getCache(THREADS); - final InOrder inOrder = Mockito.inOrder(cache); + final var cache = cacheManager.getCache(THREADS); + final var inOrder = Mockito.inOrder(cache); threadIds.forEach(id -> inOrder.verify(cache).get( - eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT.toString() + "_thread_" + id), + eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT + "_thread_" + id), eq(CommentThreads.class))); // only 1 and 3 are put into the cache as others are nulls - inOrder.verify(cache).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT.toString() + "_thread_1"), any()); - inOrder.verify(cache).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT.toString() + "_thread_3"), any()); - inOrder.verify(cache, never()).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT.toString() + "_thread_2"), any()); - inOrder.verify(cache, never()).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT.toString() + "_thread_4"), any()); + inOrder.verify(cache).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT + "_thread_1"), any()); + inOrder.verify(cache).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT + "_thread_3"), any()); + inOrder.verify(cache, never()).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT + "_thread_2"), any()); + inOrder.verify(cache, never()).put(eq(CommentService.AINT_NOBODY_GOT_TIME_FOR_THAT + "_thread_4"), any()); } @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() throws BatchServiceException, NotFoundException { + void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() + throws BatchServiceException, NotFoundException { //given // create the test request - final List threadIds = Collections.singletonList(1L); - final ThreadRequest request = ThreadRequest.builder() + final var threadIds = Collections.singletonList(1L); + final var request = ThreadRequest.builder() .articleId(CommentService.ARE_YOU_OUT_OF_QUOTA) .threadIds(threadIds) .build(); // fetch expected data - final CommentThreads expected = underTest.callBatchServiceAndPutAllToCache(request); + final var expected = underTest.callBatchServiceAndPutAllToCache(request); // verify it was just put into the cache - final Cache cache = cacheManager.getCache(THREADS); - verify(cache, never()).get(eq(CommentService.ARE_YOU_OUT_OF_QUOTA.toString() + "_thread_1"), eq(List.class)); - verify(cache).put(eq(CommentService.ARE_YOU_OUT_OF_QUOTA.toString() + "_thread_1"), any()); + final var cache = cacheManager.getCache(THREADS); + verify(cache, never()).get(eq(CommentService.ARE_YOU_OUT_OF_QUOTA + "_thread_1"), eq(List.class)); + verify(cache).put(eq(CommentService.ARE_YOU_OUT_OF_QUOTA + "_thread_1"), any()); reset(cache); // the real service is called this time - final CommentService spyService = batchServiceCaller.getCommentService(); + final var spyService = batchServiceCaller.getCommentService(); verify(spyService).threadsOf(eq(CommentService.ARE_YOU_OUT_OF_QUOTA), eq(Collections.singleton(1L))); reset(spyService); //when - final CommentThreads actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); assertEquals(1, actual.getThreads().size()); assertEquals(expected, actual); - // opportunistic processing will not call when all of the items are already cached - verify(cache).get(eq(CommentService.ARE_YOU_OUT_OF_QUOTA.toString() + "_thread_1"), eq(CommentThreads.class)); - verify(cache, never()).put(eq(CommentService.ARE_YOU_OUT_OF_QUOTA.toString() + "_thread_1"), any()); + // opportunistic processing will not call when all the items are already cached + verify(cache).get(eq(CommentService.ARE_YOU_OUT_OF_QUOTA + "_thread_1"), eq(CommentThreads.class)); + verify(cache, never()).put(eq(CommentService.ARE_YOU_OUT_OF_QUOTA + "_thread_1"), any()); // the real service is not called again verify(spyService, never()).threadsOf(eq(CommentService.ARE_YOU_OUT_OF_QUOTA), eq(Collections.singleton(1L))); } @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldUseRealServiceOnlyWhenSomeNotFoundInCache() throws BatchServiceException, NotFoundException { + void testCallCacheableBatchServiceShouldUseRealServiceOnlyWhenSomeNotFoundInCache() + throws BatchServiceException, NotFoundException { //given // warm-up cache - final ThreadRequest warmUpRequest = ThreadRequest.builder() + final var warmUpRequest = ThreadRequest.builder() .articleId(CommentService.CACHING_IS_NOT_ALWAYS_EASY).threadIds(Collections.singletonList(1L)).build(); underTest.callBatchServiceAndPutAllToCache(warmUpRequest); // verify it was just put into the cache - final Cache cache = cacheManager.getCache(THREADS); - verify(cache, never()).get(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY.toString() + "_thread_1"), eq(CommentThreads.class)); - verify(cache, atLeastOnce()).put(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY.toString() + "_thread_1"), any()); + final var cache = cacheManager.getCache(THREADS); + verify(cache, never()).get(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY + "_thread_1"), eq(CommentThreads.class)); + verify(cache, atLeastOnce()).put(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY + "_thread_1"), any()); reset(cache); // create the test request - final List threadIds = Arrays.asList(1L, 5L); - final ThreadRequest request = ThreadRequest.builder() + final var threadIds = Arrays.asList(1L, 5L); + final var request = ThreadRequest.builder() .articleId(CommentService.CACHING_IS_NOT_ALWAYS_EASY).threadIds(threadIds).build(); // fetch expected data - final CommentThreads expected = commentService.threadsOf(CommentService.CACHING_IS_NOT_ALWAYS_EASY, new HashSet<>(threadIds)); - final CommentService spyService = batchServiceCaller.getCommentService(); + final var expected = commentService.threadsOf(CommentService.CACHING_IS_NOT_ALWAYS_EASY, new HashSet<>(threadIds)); + final var spyService = batchServiceCaller.getCommentService(); verify(spyService).threadsOf(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY), eq(Collections.singleton(1L))); reset(spyService); //when - final CommentThreads actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); assertEquals(2, actual.getThreads().size()); assertEquals(expected, actual); // opportunistic processing will refresh the already cached value as well - verify(cache).get(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY.toString() + "_thread_1"), eq(CommentThreads.class)); - verify(cache).put(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY.toString() + "_thread_1"), any()); - verify(cache).get(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY.toString() + "_thread_5"), eq(CommentThreads.class)); - verify(cache).put(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY.toString() + "_thread_5"), any()); + verify(cache).get(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY + "_thread_1"), eq(CommentThreads.class)); + verify(cache).put(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY + "_thread_1"), any()); + verify(cache).get(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY + "_thread_5"), eq(CommentThreads.class)); + verify(cache).put(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY + "_thread_5"), any()); // only a single call will be made verify(spyService, never()).threadsOf(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY), eq(Collections.singleton(1L))); verify(spyService, never()).threadsOf(eq(CommentService.CACHING_IS_NOT_ALWAYS_EASY), eq(Collections.singleton(5L))); diff --git a/src/test/java/com/github/nagyesta/cacheonly/core/ParcelCacheServiceTemplateIntegrationTest.java b/src/test/java/com/github/nagyesta/cacheonly/core/ParcelCacheServiceTemplateIntegrationTest.java index 444af59..d35ef0d 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/core/ParcelCacheServiceTemplateIntegrationTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/core/ParcelCacheServiceTemplateIntegrationTest.java @@ -4,7 +4,6 @@ import com.github.nagyesta.cacheonly.example.parcel.ParcelCacheServiceTemplate; import com.github.nagyesta.cacheonly.example.parcel.ParcelContext; import com.github.nagyesta.cacheonly.example.parcel.raw.ParcelBatchServiceCaller; -import com.github.nagyesta.cacheonly.example.parcel.raw.ParcelService; import com.github.nagyesta.cacheonly.example.parcel.response.ParcelResponse; import com.github.nagyesta.cacheonly.raw.exception.BatchServiceException; import org.junit.jupiter.api.BeforeAll; @@ -23,13 +22,8 @@ import java.util.stream.IntStream; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = ParcelContext.class) @@ -70,19 +64,21 @@ private static Stream validInputProvider() { @ParameterizedTest @MethodSource("validInputProvider") void testCallCacheableBatchServiceShouldBeSplittingRequestsWhenItHasMoreItemsThanAllowed( - final List ids, final int expectedCalls) throws BatchServiceException { + final List ids, + final int expectedCalls) + throws BatchServiceException { //given // reset spy - final ParcelService spyService = batchServiceCaller.getParcelService(); + final var spyService = batchServiceCaller.getParcelService(); reset(spyService); // create the expected test response - final List expected = ids.stream() + final var expected = ids.stream() .sorted() .map(id -> new ParcelResponse(id, spyService.lookup(id))) .collect(Collectors.toList()); //when - final List actual = underTest.callCacheableBatchService(ids); + final var actual = underTest.callCacheableBatchService(ids); //then if (expectedCalls == 0) { diff --git a/src/test/java/com/github/nagyesta/cacheonly/core/StockCacheServiceTemplateIntegrationTest.java b/src/test/java/com/github/nagyesta/cacheonly/core/StockCacheServiceTemplateIntegrationTest.java index b6f3de0..6f20a8e 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/core/StockCacheServiceTemplateIntegrationTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/core/StockCacheServiceTemplateIntegrationTest.java @@ -7,33 +7,19 @@ import com.github.nagyesta.cacheonly.raw.exception.BatchServiceException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InOrder; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.math.BigDecimal; -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.*; import static com.github.nagyesta.cacheonly.example.stock.StockContext.STOCKS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = StockContext.class) @@ -51,20 +37,21 @@ class StockCacheServiceTemplateIntegrationTest { @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldNotPutAnythingWhenNoResultsFound() throws BatchServiceException { + void testCallCacheableBatchServiceShouldNotPutAnythingWhenNoResultsFound() + throws BatchServiceException { //given // create the test request final SortedSet request = new TreeSet<>(Arrays.asList("A", "B", "C")); //when - final SortedMap actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); assertEquals(Collections.emptyMap(), actual); // all items were tried from the cache and missed - final Cache cache = cacheManager.getCache(STOCKS); - final InOrder inOrder = Mockito.inOrder(cache); + final var cache = cacheManager.getCache(STOCKS); + final var inOrder = Mockito.inOrder(cache); inOrder.verify(cache).get(eq("price_A"), eq(BigDecimal.class)); // pessimistic strategy aborts after first failure inOrder.verify(cache, never()).get(eq("price_B"), eq(BigDecimal.class)); @@ -75,14 +62,15 @@ void testCallCacheableBatchServiceShouldNotPutAnythingWhenNoResultsFound() throw @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldCacheWhenResultsAreFound() throws BatchServiceException { + void testCallCacheableBatchServiceShouldCacheWhenResultsAreFound() + throws BatchServiceException { //given // create the test request final SortedSet request = new TreeSet<>(Arrays.asList(StockService.AAPL, StockService.AMD, StockService.EPAM, "UNKNOWN")); - final Map expected = stockService.lookupNoLimit(request); + final var expected = stockService.lookupNoLimit(request); //when - final SortedMap actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); @@ -90,9 +78,9 @@ void testCallCacheableBatchServiceShouldCacheWhenResultsAreFound() throws BatchS assertIterableEquals(Arrays.asList(StockService.AAPL, StockService.AMD, StockService.EPAM), actual.keySet()); assertEquals(expected, actual); // all items were tried from the cache and missed - final Cache cache = cacheManager.getCache(STOCKS); - final StockService spyService = batchServiceCaller.getStockService(); - final InOrder inOrder = Mockito.inOrder(cache, spyService); + final var cache = cacheManager.getCache(STOCKS); + final var spyService = batchServiceCaller.getStockService(); + final var inOrder = Mockito.inOrder(cache, spyService); inOrder.verify(cache).get(eq("price_" + StockService.AAPL), eq(BigDecimal.class)); // pessimistic strategy aborts after first failure inOrder.verify(cache, never()).get(eq("price_" + StockService.AMD), eq(BigDecimal.class)); @@ -109,14 +97,15 @@ void testCallCacheableBatchServiceShouldCacheWhenResultsAreFound() throws BatchS @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() throws BatchServiceException { + void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() + throws BatchServiceException { //given // create the test request final SortedSet request = new TreeSet<>(Arrays.asList(StockService.AAPL, StockService.AMD, StockService.EPAM)); final Map expected = underTest.callBatchServiceAndPutAllToCache(request); // verify that items where just put into cache - final Cache cache = cacheManager.getCache(STOCKS); - final StockService spyService = batchServiceCaller.getStockService(); + final var cache = cacheManager.getCache(STOCKS); + final var spyService = batchServiceCaller.getStockService(); verify(spyService).lookup(eq(new TreeSet<>(Arrays.asList(StockService.AAPL, StockService.EPAM)))); verify(spyService).lookup(eq(new TreeSet<>(Collections.singletonList(StockService.AMD)))); reset(spyService); @@ -126,7 +115,7 @@ void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() t reset(cache); //when - final SortedMap actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); @@ -134,7 +123,7 @@ void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() t assertIterableEquals(Arrays.asList(StockService.AAPL, StockService.AMD, StockService.EPAM), actual.keySet()); assertEquals(expected, actual); // all items were tried from the cache and missed - final InOrder inOrder = Mockito.inOrder(cache, spyService); + final var inOrder = Mockito.inOrder(cache, spyService); inOrder.verify(cache).get(eq("price_" + StockService.AAPL), eq(BigDecimal.class)); inOrder.verify(cache).get(eq("price_" + StockService.EPAM), eq(BigDecimal.class)); inOrder.verify(cache).get(eq("price_" + StockService.AMD), eq(BigDecimal.class)); @@ -148,24 +137,25 @@ void testCallCacheableBatchServiceShouldNotUseRealServiceWhenAllFoundInCache() t @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - void testCallCacheableBatchServiceShouldUseRealServiceOnlyWhenSomeNotFoundInCache() throws BatchServiceException { + void testCallCacheableBatchServiceShouldUseRealServiceOnlyWhenSomeNotFoundInCache() + throws BatchServiceException { //given // create the warm-up request final SortedSet warmUpRequest = new TreeSet<>(Collections.singletonList(StockService.AAPL)); underTest.callBatchServiceAndPutAllToCache(warmUpRequest); // verify that items where just put into cache - final Cache cache = cacheManager.getCache(STOCKS); - final StockService spyService = batchServiceCaller.getStockService(); + final var cache = cacheManager.getCache(STOCKS); + final var spyService = batchServiceCaller.getStockService(); verify(spyService).lookup(eq(new TreeSet<>(Collections.singletonList(StockService.AAPL)))); reset(spyService); verify(cache).put(eq("price_" + StockService.AAPL), any()); reset(cache); // create the test request final SortedSet request = new TreeSet<>(Arrays.asList(StockService.AAPL, StockService.AMD, StockService.EPAM)); - final Map expected = stockService.lookupNoLimit(request); + final var expected = stockService.lookupNoLimit(request); //when - final SortedMap actual = underTest.callCacheableBatchService(request); + final var actual = underTest.callCacheableBatchService(request); //then assertNotNull(actual); @@ -173,7 +163,7 @@ void testCallCacheableBatchServiceShouldUseRealServiceOnlyWhenSomeNotFoundInCach assertIterableEquals(Arrays.asList(StockService.AAPL, StockService.AMD, StockService.EPAM), actual.keySet()); assertEquals(expected, actual); // all items were tried from the cache and missed - final InOrder inOrder = Mockito.inOrder(cache, spyService); + final var inOrder = Mockito.inOrder(cache, spyService); inOrder.verify(cache).get(eq("price_" + StockService.AAPL), eq(BigDecimal.class)); inOrder.verify(cache).get(eq("price_" + StockService.EPAM), eq(BigDecimal.class)); // pessimistic strategy aborts after first failure diff --git a/src/test/java/com/github/nagyesta/cacheonly/core/UnstableCacheServiceTemplateTest.java b/src/test/java/com/github/nagyesta/cacheonly/core/UnstableCacheServiceTemplateTest.java index fb94007..69fc44a 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/core/UnstableCacheServiceTemplateTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/core/UnstableCacheServiceTemplateTest.java @@ -14,11 +14,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; @SuppressWarnings("checkstyle:MagicNumber") class UnstableCacheServiceTemplateTest { @@ -31,110 +27,110 @@ static void beforeAll() { @Test public void testExceptionsAreHandledWhenBothCacheAndOriginFails() { //given - final UnstableCacheServiceTemplate underTest = new UnstableCacheServiceTemplate(); - final BasicBatchServiceCallMetricCollector metricCollector = new BasicBatchServiceCallMetricCollector(); + final var underTest = new UnstableCacheServiceTemplate(); + final var metricCollector = new BasicBatchServiceCallMetricCollector(); underTest.setMetricsCollector(metricCollector); - final List input = Arrays.asList(0L, 1L, 2L, 3L, 4L); + final var input = Arrays.asList(0L, 1L, 2L, 3L, 4L); //when - final List actual = underTest.callCacheableBatchService(input); + final var actual = underTest.callCacheableBatchService(input); //then assertNull(actual); - assertEquals(metricCollector.getCacheGet(), 5); - assertEquals(metricCollector.getCacheMiss(), 5); - assertEquals(metricCollector.getCacheHit(), 0); - assertEquals(metricCollector.getPartitionCreated(), 1); - assertEquals(metricCollector.getPartitionFailed(), 0); - assertEquals(metricCollector.getPartitionSucceeded(), 1); + assertEquals(5, metricCollector.getCacheGet()); + assertEquals(5, metricCollector.getCacheMiss()); + assertEquals(0, metricCollector.getCacheHit()); + assertEquals(1, metricCollector.getPartitionCreated()); + assertEquals(0, metricCollector.getPartitionFailed()); + assertEquals(1, metricCollector.getPartitionSucceeded()); } @Test public void testExceptionsAreHandledWhenCalledWithEmptyList() { //given - final UnstableCacheServiceTemplate underTest = new UnstableCacheServiceTemplate(); - final BasicBatchServiceCallMetricCollector metricCollector = new BasicBatchServiceCallMetricCollector(); + final var underTest = new UnstableCacheServiceTemplate(); + final var metricCollector = new BasicBatchServiceCallMetricCollector(); underTest.setMetricsCollector(metricCollector); final List input = Collections.emptyList(); //when - final List actual = underTest.callCacheableBatchService(input); + final var actual = underTest.callCacheableBatchService(input); //then assertNull(actual); - assertEquals(metricCollector.getCacheGet(), 0); - assertEquals(metricCollector.getCacheMiss(), 0); - assertEquals(metricCollector.getCacheHit(), 0); - assertEquals(metricCollector.getPartitionCreated(), 0); - assertEquals(metricCollector.getPartitionFailed(), 0); - assertEquals(metricCollector.getPartitionSucceeded(), 0); + assertEquals(0, metricCollector.getCacheGet()); + assertEquals(0, metricCollector.getCacheMiss()); + assertEquals(0, metricCollector.getCacheHit()); + assertEquals(0, metricCollector.getPartitionCreated()); + assertEquals(0, metricCollector.getPartitionFailed()); + assertEquals(0, metricCollector.getPartitionSucceeded()); } @Test @Timeout(value = 60, unit = TimeUnit.MILLISECONDS) public void testExceptionsAreHandledWhenBothCacheAndOriginTimesOut() { //given - final UnstableCacheServiceTemplate underTest = new UnstableCacheServiceTemplate(); - final BasicBatchServiceCallMetricCollector metricCollector = new BasicBatchServiceCallMetricCollector(); + final var underTest = new UnstableCacheServiceTemplate(); + final var metricCollector = new BasicBatchServiceCallMetricCollector(); underTest.setMetricsCollector(metricCollector); - final List input = Arrays.asList(-40L, -31L, -32L, -33L, -44L); + final var input = Arrays.asList(-40L, -31L, -32L, -33L, -44L); //when assertThrows(BatchServiceException.class, () -> underTest.callCacheableBatchService(input)); //then + exception - assertEquals(metricCollector.getCacheGet(), 5); - assertEquals(metricCollector.getCacheMiss(), 5); - assertEquals(metricCollector.getCacheHit(), 0); - assertEquals(metricCollector.getPartitionCreated(), 1); - assertEquals(metricCollector.getPartitionFailed(), 1); - assertEquals(metricCollector.getPartitionSucceeded(), 0); + assertEquals(5, metricCollector.getCacheGet()); + assertEquals(5, metricCollector.getCacheMiss()); + assertEquals(0, metricCollector.getCacheHit()); + assertEquals(1, metricCollector.getPartitionCreated()); + assertEquals(1, metricCollector.getPartitionFailed()); + assertEquals(0, metricCollector.getPartitionSucceeded()); } @Test public void testExceptionsAreHandledWhenCallsResultErrors() { //given - final UnstableCacheServiceTemplate underTest = new UnstableCacheServiceTemplate(); - final BasicBatchServiceCallMetricCollector metricCollector = new BasicBatchServiceCallMetricCollector(); + final var underTest = new UnstableCacheServiceTemplate(); + final var metricCollector = new BasicBatchServiceCallMetricCollector(); underTest.setMetricsCollector(metricCollector); - final List input = Collections.singletonList(-15L); + final var input = Collections.singletonList(-15L); //when assertThrows(BatchServiceException.class, () -> underTest.callCacheableBatchService(input)); //then + exception - assertEquals(metricCollector.getCacheGet(), 1); - assertEquals(metricCollector.getCacheMiss(), 1); - assertEquals(metricCollector.getCacheHit(), 0); - assertEquals(metricCollector.getPartitionCreated(), 1); - assertEquals(metricCollector.getPartitionFailed(), 1); - assertEquals(metricCollector.getPartitionSucceeded(), 0); + assertEquals(1, metricCollector.getCacheGet()); + assertEquals(1, metricCollector.getCacheMiss()); + assertEquals(0, metricCollector.getCacheHit()); + assertEquals(1, metricCollector.getPartitionCreated()); + assertEquals(1, metricCollector.getPartitionFailed()); + assertEquals(0, metricCollector.getPartitionSucceeded()); } @Test public void testHappyCaseIsWorkingWhenFoundInCache() { //given - final UnstableCacheServiceTemplate underTest = new UnstableCacheServiceTemplate(); - final BasicBatchServiceCallMetricCollector metricCollector = new BasicBatchServiceCallMetricCollector(); + final var underTest = new UnstableCacheServiceTemplate(); + final var metricCollector = new BasicBatchServiceCallMetricCollector(); underTest.setMetricsCollector(metricCollector); - final List input = Collections.singletonList(19L); + final var input = Collections.singletonList(19L); //when - final List actual = underTest.callCacheableBatchService(input); + final var actual = underTest.callCacheableBatchService(input); //then assertNotNull(actual); assertIterableEquals(Collections.singletonList("19"), actual); - assertEquals(metricCollector.getCacheGet(), 1); - assertEquals(metricCollector.getCacheMiss(), 0); - assertEquals(metricCollector.getCacheHit(), 1); - assertEquals(metricCollector.getPartitionCreated(), 0); - assertEquals(metricCollector.getPartitionFailed(), 0); - assertEquals(metricCollector.getPartitionSucceeded(), 0); + assertEquals(1, metricCollector.getCacheGet()); + assertEquals(0, metricCollector.getCacheMiss()); + assertEquals(1, metricCollector.getCacheHit()); + assertEquals(0, metricCollector.getPartitionCreated()); + assertEquals(0, metricCollector.getPartitionFailed()); + assertEquals(0, metricCollector.getPartitionSucceeded()); } } diff --git a/src/test/java/com/github/nagyesta/cacheonly/entity/CacheKeyTest.java b/src/test/java/com/github/nagyesta/cacheonly/entity/CacheKeyTest.java index 6023f4d..613352e 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/entity/CacheKeyTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/entity/CacheKeyTest.java @@ -15,7 +15,7 @@ class CacheKeyTest { @SuppressWarnings({"UnnecessaryBoxing", "checkstyle:MagicNumber"}) private static Stream keyPairProvider() { - final CacheKey aCacheKey = new CacheKey<>(KEY_1, 1); + final var aCacheKey = new CacheKey<>(KEY_1, 1); return Stream.builder() .add(Arguments.of(aCacheKey, aCacheKey, true)) .add(Arguments.of(new CacheKey<>(KEY_1, 1), new CacheKey<>(KEY_2, 1), false)) @@ -27,11 +27,14 @@ private static Stream keyPairProvider() { @ParameterizedTest @MethodSource("keyPairProvider") - void testEqualsShouldCompareBothFieldsWhenCalled(final Object a, final Object b, final boolean expected) { + void testEqualsShouldCompareBothFieldsWhenCalled( + final Object a, + final Object b, + final boolean expected) { //given //when - final boolean actual = a.equals(b); + final var actual = a.equals(b); //then assertEquals(expected, actual); @@ -39,12 +42,15 @@ void testEqualsShouldCompareBothFieldsWhenCalled(final Object a, final Object b, @ParameterizedTest @MethodSource("keyPairProvider") - void testHashCodeShouldCompareBothFieldsWhenCalled(final Object a, final Object b, final boolean expected) { + void testHashCodeShouldCompareBothFieldsWhenCalled( + final Object a, + final Object b, + final boolean expected) { //given //when - final int hashA = a.hashCode(); - final int hashB = b.hashCode(); + final var hashA = a.hashCode(); + final var hashB = b.hashCode(); //then assertEquals(expected, hashA == hashB); diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/raw/ParcelService.java b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/raw/ParcelService.java index 8331f04..f3f25ed 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/raw/ParcelService.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/raw/ParcelService.java @@ -21,7 +21,7 @@ public List lookup(final List batchRequest) { } public ParcelStatus lookup(final String id) { - ParcelStatus result = ParcelStatus.NEW; + var result = ParcelStatus.NEW; if (id.startsWith("A")) { result = ParcelStatus.PICKED_UP; } else if (id.startsWith("B")) { diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/response/ParcelResponse.java b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/response/ParcelResponse.java index 649100d..0b5f836 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/response/ParcelResponse.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/response/ParcelResponse.java @@ -1,13 +1,4 @@ package com.github.nagyesta.cacheonly.example.parcel.response; -import lombok.AllArgsConstructor; -import lombok.Data; -import org.springframework.cache.annotation.EnableCaching; - -@Data -@AllArgsConstructor -@EnableCaching -public class ParcelResponse { - private String id; - private ParcelStatus status; +public record ParcelResponse(String id, ParcelStatus status) { } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelBatchResponseTransformer.java b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelBatchResponseTransformer.java index 9cc7d50..f5a9ab7 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelBatchResponseTransformer.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelBatchResponseTransformer.java @@ -16,12 +16,13 @@ public class ParcelBatchResponseTransformer extends CollectionBasedResponseTransformer, ParcelResponse, String> { public ParcelBatchResponseTransformer() { - super(Collectors.toList(), ParcelResponse::getId, true); + super(Collectors.toList(), ParcelResponse::id, true); } @Nullable @Override - public List mergeToBatchResponse(final @NotNull Map entityMap) { + public List mergeToBatchResponse( + final @NotNull Map entityMap) { return super.mergeToBatchResponse(new TreeMap<>(entityMap)); } } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelPartialCacheSupport.java b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelPartialCacheSupport.java index 7687c72..78f1972 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelPartialCacheSupport.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/parcel/transform/ParcelPartialCacheSupport.java @@ -5,6 +5,7 @@ import org.springframework.stereotype.Component; @Component -public class ParcelPartialCacheSupport extends NoOpPartialCacheSupport { +public class ParcelPartialCacheSupport + extends NoOpPartialCacheSupport { } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/replies/CommentContext.java b/src/test/java/com/github/nagyesta/cacheonly/example/replies/CommentContext.java index 9c20165..b9f3525 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/replies/CommentContext.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/replies/CommentContext.java @@ -24,7 +24,7 @@ public class CommentContext { @Bean public CacheManager cacheManager() { - final SimpleCacheManager cacheManager = new SimpleCacheManager(); + final var cacheManager = new SimpleCacheManager(); cacheManager.setCaches(Collections.singletonList(spy(new ConcurrentMapCache(THREADS)))); return cacheManager; } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/replies/raw/CommentService.java b/src/test/java/com/github/nagyesta/cacheonly/example/replies/raw/CommentService.java index 75374c9..aa1c4df 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/replies/raw/CommentService.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/replies/raw/CommentService.java @@ -6,13 +6,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.Assert; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; @Service @@ -30,9 +24,7 @@ public class CommentService { private final Map> database; CommentService() { - final Map> map = new HashMap<>(); - map.put(NO_COMMENT, Collections.emptyList()); - map.put(CACHING_IS_NOT_ALWAYS_EASY, Collections.unmodifiableList(Arrays.asList( + this.database = Map.of(NO_COMMENT, Collections.emptyList(), CACHING_IS_NOT_ALWAYS_EASY, Collections.unmodifiableList(Arrays.asList( Comment.builder() .articleId(CACHING_IS_NOT_ALWAYS_EASY) .commentId(1L) @@ -79,8 +71,7 @@ public class CommentService { .author(S_SERIOUS) .message("I am looking for one too, could you send a link?") .build() - ))); - map.put(ARE_YOU_OUT_OF_QUOTA, Collections.unmodifiableList(Arrays.asList( + )), ARE_YOU_OUT_OF_QUOTA, Collections.unmodifiableList(Arrays.asList( Comment.builder() .articleId(ARE_YOU_OUT_OF_QUOTA) .commentId(1L) @@ -101,8 +92,7 @@ public class CommentService { .author(O_PEN) .message("It happens.") .build() - ))); - map.put(AINT_NOBODY_GOT_TIME_FOR_THAT, Collections.unmodifiableList(Arrays.asList( + )), AINT_NOBODY_GOT_TIME_FOR_THAT, Collections.unmodifiableList(Arrays.asList( Comment.builder() .articleId(AINT_NOBODY_GOT_TIME_FOR_THAT) .commentId(1L) @@ -130,20 +120,22 @@ public class CommentService { .message("LOL, more like third.") .build() ))); - this.database = Collections.unmodifiableMap(map); } @NotNull - public CommentThreads threadsOf(final @NotNull UUID article, final @NotNull Set threadIds) throws NotFoundException { + public CommentThreads threadsOf( + final @NotNull UUID article, + final @NotNull Set threadIds) + throws NotFoundException { Assert.isTrue(threadIds.size() <= 5, "Batch size is too large."); if (!database.containsKey(article)) { throw new NotFoundException(); } - final Set threadStarters = this.database.get(article).stream() + final var threadStarters = this.database.get(article).stream() .filter(comment -> comment.getThreadId() == null) .map(Comment::getCommentId) .collect(Collectors.toSet()); - final Map> threads = this.database.get(article).stream() + final var threads = this.database.get(article).stream() .filter(comment -> comment.getThreadId() != null) .filter(comment -> threadIds.contains(comment.getThreadId())) .collect(Collectors.groupingBy(Comment::getThreadId)); diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/replies/request/ThreadRequest.java b/src/test/java/com/github/nagyesta/cacheonly/example/replies/request/ThreadRequest.java index 0254fdf..315cbad 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/replies/request/ThreadRequest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/replies/request/ThreadRequest.java @@ -15,7 +15,9 @@ public class ThreadRequest { public ThreadRequest() { } - public ThreadRequest(final UUID articleId, final List threadIds) { + public ThreadRequest( + final UUID articleId, + final List threadIds) { this.articleId = articleId; this.threadIds = threadIds; } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentBatchBasedRequestTransformer.java b/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentBatchBasedRequestTransformer.java index 61542f9..1ef1910 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentBatchBasedRequestTransformer.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentBatchBasedRequestTransformer.java @@ -9,7 +9,8 @@ import java.util.stream.Collectors; @Component -public class CommentBatchBasedRequestTransformer extends WrappedCollectionBasedRequestTransformer, Long, Long> { +public class CommentBatchBasedRequestTransformer + extends WrappedCollectionBasedRequestTransformer, Long, Long> { public CommentBatchBasedRequestTransformer() { super(ThreadRequest::new, ThreadRequest::getThreadIds, (request, threadIds) -> { diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentPartialCacheSupport.java b/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentPartialCacheSupport.java index a577f26..d69e4ec 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentPartialCacheSupport.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/replies/transform/CommentPartialCacheSupport.java @@ -35,7 +35,7 @@ public Class getEntityClass() { @NotNull @Override public CacheKey toCacheKey(final @NotNull ThreadRequest partialRequest) { - final Long id = partialRequest.getThreadIds().get(0); + final var id = partialRequest.getThreadIds().get(0); return new CacheKey<>(partialRequest.getArticleId().toString() + "_thread_" + id, id); } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/stock/StockContext.java b/src/test/java/com/github/nagyesta/cacheonly/example/stock/StockContext.java index 478fa88..b7bf150 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/stock/StockContext.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/stock/StockContext.java @@ -24,7 +24,7 @@ public class StockContext { @Bean public CacheManager cacheManager() { - final SimpleCacheManager cacheManager = new SimpleCacheManager(); + final var cacheManager = new SimpleCacheManager(); cacheManager.setCaches(Collections.singletonList(spy(new ConcurrentMapCache(STOCKS)))); return cacheManager; } diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/stock/raw/StockBatchServiceCaller.java b/src/test/java/com/github/nagyesta/cacheonly/example/stock/raw/StockBatchServiceCaller.java index 3074cfa..f4463d2 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/stock/raw/StockBatchServiceCaller.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/stock/raw/StockBatchServiceCaller.java @@ -41,7 +41,8 @@ public CacheRefreshStrategy refreshStrategy() { @NotNull @Override @SuppressWarnings("RedundantThrows") - public SortedMap callBatchService(final @NotNull SortedSet batchRequest) + public SortedMap callBatchService( + final @NotNull SortedSet batchRequest) throws BatchServiceException { // we call the service here return new TreeMap<>(stockService.lookup(batchRequest)); diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableCacheServiceTemplate.java b/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableCacheServiceTemplate.java index 20a5ce3..e1436ca 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableCacheServiceTemplate.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableCacheServiceTemplate.java @@ -15,7 +15,7 @@ public class UnstableCacheServiceTemplate extends ConcurrentCacheServiceTemplate, List, Long, String, String, Long> { private static final BatchRequestTransformer, Long, Long> BATCH_REQUEST_TRANSFORMER = - new BatchRequestTransformer, Long, Long>() { + new BatchRequestTransformer<>() { @NotNull @Override public Map splitToPartialRequest(final @NotNull List batchRequest) { @@ -32,7 +32,7 @@ public List mergeToBatchRequest(final @NotNull Map requestMap) } }; private static final BatchResponseTransformer, String, Long> BATCH_RESPONSE_TRANSFORMER = - new BatchResponseTransformer, String, Long>() { + new BatchResponseTransformer<>() { @NotNull @Override public Map splitToPartialResponse(final @NotNull List batchResponse) { diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableConcurrentBatchServiceCaller.java b/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableConcurrentBatchServiceCaller.java index 68770ed..9fc1432 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableConcurrentBatchServiceCaller.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstableConcurrentBatchServiceCaller.java @@ -38,9 +38,10 @@ public int maxPartitionSize() { @Nullable @Override - public List callBatchService(final @NotNull List batchRequest) throws BatchServiceException { + public List callBatchService(final @NotNull List batchRequest) + throws BatchServiceException { handleExceptionalCases(batchRequest); - final List result = batchRequest.stream() + final var result = batchRequest.stream() .filter(i -> i > 10) .map(String::valueOf) .collect(Collectors.toList()); @@ -54,9 +55,9 @@ public List callBatchService(final @NotNull List batchRequest) thr private void handleExceptionalCases(final @NotNull List batchRequest) { if (batchRequest.stream().anyMatch(i -> i < -30L)) { try { - final long start = System.currentTimeMillis(); + final var start = System.currentTimeMillis(); Thread.sleep(60); - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); log.trace("Took: {} ms", (end - start)); } catch (final InterruptedException e) { log.error(e.getMessage(), e); diff --git a/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstablePartialCacheSupport.java b/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstablePartialCacheSupport.java index ceac34d..518b503 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstablePartialCacheSupport.java +++ b/src/test/java/com/github/nagyesta/cacheonly/example/unstable/UnstablePartialCacheSupport.java @@ -52,21 +52,21 @@ public CacheManager getCacheManager() { @Override public String getFromCache(final @NotNull CacheKey key) { handleExceptionalCases(key); - if (key.getId() < 5 || key.getId() > 20) { + if (key.id() < 5 || key.id() > 20) { return null; } - return key.getKey(); + return key.key(); } private void handleExceptionalCases(final @NotNull CacheKey key) { - if (key.getId() == -15L) { + if (key.id() == -15L) { throw new IllegalStateException("Get failed."); } - if (key.getId() < -30) { + if (key.id() < -30) { try { - final long start = System.currentTimeMillis(); + final var start = System.currentTimeMillis(); Thread.sleep(60); - final long end = System.currentTimeMillis(); + final var end = System.currentTimeMillis(); log.trace("Took: {} ms", (end - start)); } catch (final InterruptedException e) { log.error(e.getMessage(), e); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/CollectionWrapper.java b/src/test/java/com/github/nagyesta/cacheonly/transform/CollectionWrapper.java index 5c5e34a..53f5498 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/CollectionWrapper.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/CollectionWrapper.java @@ -1,11 +1,15 @@ package com.github.nagyesta.cacheonly.transform; +import lombok.Getter; +import lombok.Setter; import org.apache.commons.collections4.CollectionUtils; import java.util.Collection; import java.util.Objects; import java.util.StringJoiner; +@Setter +@Getter public final class CollectionWrapper { private Collection collection; @@ -14,23 +18,14 @@ public CollectionWrapper(final Collection collection) { this.collection = collection; } - public Collection getCollection() { - return collection; - } - - public void setCollection(final Collection collection) { - this.collection = collection; - } - @Override public boolean equals(final Object o) { if (this == o) { return true; } - if (!(o instanceof CollectionWrapper)) { + if (!(o instanceof final CollectionWrapper that)) { return false; } - final CollectionWrapper that = (CollectionWrapper) o; return CollectionUtils.containsAll(this.collection, that.collection) && CollectionUtils.containsAll(that.collection, this.collection); } diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/MapWrapper.java b/src/test/java/com/github/nagyesta/cacheonly/transform/MapWrapper.java index 352d609..6f3c4ee 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/MapWrapper.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/MapWrapper.java @@ -1,9 +1,14 @@ package com.github.nagyesta.cacheonly.transform; +import lombok.Getter; +import lombok.Setter; + import java.util.Map; import java.util.Objects; import java.util.StringJoiner; +@Setter +@Getter public final class MapWrapper { private Map map; @@ -12,23 +17,14 @@ public MapWrapper(final Map map) { this.map = map; } - public Map getMap() { - return map; - } - - public void setMap(final Map map) { - this.map = map; - } - @Override public boolean equals(final Object o) { if (this == o) { return true; } - if (!(o instanceof MapWrapper)) { + if (!(o instanceof final MapWrapper that)) { return false; } - final MapWrapper that = (MapWrapper) o; return Objects.equals(map, that.map); } diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformerTest.java index 140e087..3c86b6d 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedRequestTransformerTest.java @@ -13,9 +13,7 @@ import java.util.stream.LongStream; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; @SuppressWarnings("checkstyle:MagicNumber") class CollectionBasedRequestTransformerTest { @@ -49,14 +47,15 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialRequestShouldSplitValidInput(final List input, - final Map expected) { + void testSplitToPartialRequestShouldSplitValidInput( + final List input, + final Map expected) { //given - final CollectionBasedRequestTransformer, String, Long> underTest = - new CollectionBasedRequestTransformer<>(Collectors.toList(), Long::parseLong); + final var underTest = + new CollectionBasedRequestTransformer, String, Long>(Collectors.toList(), Long::parseLong); //when - final Map actual = underTest.splitToPartialRequest(input); + final var actual = underTest.splitToPartialRequest(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -64,14 +63,16 @@ void testSplitToPartialRequestShouldSplitValidInput(final List input, @ParameterizedTest @MethodSource("mergeInputProvider") - void testMergeToBatchRequestShouldMergeValidInput(final Map input, - final List expected) { + void testMergeToBatchRequestShouldMergeValidInput( + final Map input, + final List expected) { //given - final CollectionBasedRequestTransformer, String, Long> underTest = - new CollectionBasedRequestTransformer<>(Collectors.toList(), Long::parseLong); + final var underTest = + new CollectionBasedRequestTransformer, String, Long>( + Collectors.toList(), Long::parseLong); //when - final List actual = underTest.mergeToBatchRequest(input); + final var actual = underTest.mergeToBatchRequest(input); //then assertNotNull(actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformerTest.java index 09c6eee..53ae70f 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/CollectionBasedResponseTransformerTest.java @@ -13,9 +13,7 @@ import java.util.stream.LongStream; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; @SuppressWarnings("checkstyle:MagicNumber") class CollectionBasedResponseTransformerTest { @@ -49,14 +47,16 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialResponseShouldSplitValidInput(final List input, - final Map expected) { + void testSplitToPartialResponseShouldSplitValidInput( + final List input, + final Map expected) { //given - final CollectionBasedResponseTransformer, String, Long> underTest = - new CollectionBasedResponseTransformer<>(Collectors.toList(), Long::parseLong); + final var underTest = + new CollectionBasedResponseTransformer, String, Long>( + Collectors.toList(), Long::parseLong); //when - final Map actual = underTest.splitToPartialResponse(input); + final var actual = underTest.splitToPartialResponse(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -64,14 +64,16 @@ void testSplitToPartialResponseShouldSplitValidInput(final List input, @ParameterizedTest @MethodSource("mergeInputProvider") - void testMergeToBatchResponseShouldMergeValidInput(final Map input, - final List expected) { + void testMergeToBatchResponseShouldMergeValidInput( + final Map input, + final List expected) { //given - final CollectionBasedResponseTransformer, String, Long> underTest = - new CollectionBasedResponseTransformer<>(Collectors.toList(), Long::parseLong, false); + final var underTest = + new CollectionBasedResponseTransformer, String, Long>( + Collectors.toList(), Long::parseLong, false); //when - final List actual = underTest.mergeToBatchResponse(input); + final var actual = underTest.mergeToBatchResponse(input); //then assertNotNull(actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformerTest.java index 5ce5e2d..ace573b 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedRequestTransformerTest.java @@ -46,14 +46,15 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialRequestShouldSplitValidInput(final SortedMap input, - final Map expected) { + void testSplitToPartialRequestShouldSplitValidInput( + final SortedMap input, + final Map expected) { //given - final MapBasedRequestTransformer, String, Long> underTest = - new MapBasedRequestTransformer<>(TreeMap::new); + final var underTest = + new MapBasedRequestTransformer, String, Long>(TreeMap::new); //when - final Map actual = underTest.splitToPartialRequest(input); + final var actual = underTest.splitToPartialRequest(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -61,15 +62,18 @@ void testSplitToPartialRequestShouldSplitValidInput(final SortedMap input, - final SortedMap expected) { + void testMergeToBatchRequestShouldMergeValidInput( + final Map input, + final SortedMap expected) { //given - final MapBasedRequestTransformer, String, Long> underTest = - new MapBasedRequestTransformer<>(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (T, U) -> T, TreeMap::new), - Map.Entry::getKey, Map.Entry::getValue); + final var underTest = + new MapBasedRequestTransformer, String, Long>( + Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (T, U) -> T, TreeMap::new), + Map.Entry::getKey, + Map.Entry::getValue); //when - final SortedMap actual = underTest.mergeToBatchRequest(input); + final var actual = underTest.mergeToBatchRequest(input); //then assertEquals(expected, actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformerTest.java index 828f134..09d79a1 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/MapBasedResponseTransformerTest.java @@ -46,14 +46,15 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialResponseShouldSplitValidInput(final SortedMap input, - final Map expected) { + void testSplitToPartialResponseShouldSplitValidInput( + final SortedMap input, + final Map expected) { //given - final MapBasedResponseTransformer, String, Long> underTest = - new MapBasedResponseTransformer<>(TreeMap::new); + final var underTest = + new MapBasedResponseTransformer, String, Long>(TreeMap::new); //when - final Map actual = underTest.splitToPartialResponse(input); + final var actual = underTest.splitToPartialResponse(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -61,15 +62,18 @@ void testSplitToPartialResponseShouldSplitValidInput(final SortedMap input, - final SortedMap expected) { + void testMergeToBatchResponseShouldMergeValidInput( + final Map input, + final SortedMap expected) { //given - final MapBasedResponseTransformer, String, Long> underTest = - new MapBasedResponseTransformer<>(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (T, U) -> T, TreeMap::new), - Map.Entry::getKey, Map.Entry::getValue, true); + final var underTest = + new MapBasedResponseTransformer, String, Long>( + Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (T, U) -> T, TreeMap::new), + Map.Entry::getKey, + Map.Entry::getValue, true); //when - final SortedMap actual = underTest.mergeToBatchResponse(input); + final var actual = underTest.mergeToBatchResponse(input); //then assertEquals(expected, actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformerTest.java index 21ee198..d2ec79c 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedRequestTransformerTest.java @@ -51,11 +51,13 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialRequestShouldSplitValidInput(final CollectionWrapper input, - final Map> expected) { + void testSplitToPartialRequestShouldSplitValidInput( + final CollectionWrapper input, + final Map> expected) { //given - final WrappedCollectionBasedRequestTransformer, Collection, String, Long> underTest = - new WrappedCollectionBasedRequestTransformer<>(() -> new CollectionWrapper<>(new ArrayList<>()), + final var underTest = + new WrappedCollectionBasedRequestTransformer, Collection, String, Long>( + () -> new CollectionWrapper<>(new ArrayList<>()), CollectionWrapper::getCollection, (wrapper, collection) -> { wrapper.setCollection(collection); @@ -63,7 +65,7 @@ void testSplitToPartialRequestShouldSplitValidInput(final CollectionWrapper> actual = underTest.splitToPartialRequest(input); + final var actual = underTest.splitToPartialRequest(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -71,11 +73,13 @@ void testSplitToPartialRequestShouldSplitValidInput(final CollectionWrapper> input, - final CollectionWrapper expected) { + void testMergeToBatchRequestShouldMergeValidInput( + final Map> input, + final CollectionWrapper expected) { //given - final WrappedCollectionBasedRequestTransformer, Collection, String, Long> underTest = - new WrappedCollectionBasedRequestTransformer<>(w -> new CollectionWrapper<>(new ArrayList<>()), + final var underTest = + new WrappedCollectionBasedRequestTransformer, Collection, String, Long>( + w -> new CollectionWrapper<>(new ArrayList<>()), CollectionWrapper::getCollection, (wrapper, collection) -> { wrapper.setCollection(collection); @@ -83,7 +87,7 @@ void testMergeToBatchRequestShouldMergeValidInput(final Map actual = underTest.mergeToBatchRequest(input); + final var actual = underTest.mergeToBatchRequest(input); //then assertEquals(expected, actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformerTest.java index a738fc3..bca6659 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedCollectionBasedResponseTransformerTest.java @@ -51,11 +51,13 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialResponseShouldSplitValidInput(final CollectionWrapper input, - final Map> expected) { + void testSplitToPartialResponseShouldSplitValidInput( + final CollectionWrapper input, + final Map> expected) { //given - final WrappedCollectionBasedResponseTransformer, Collection, String, Long> underTest = - new WrappedCollectionBasedResponseTransformer<>(() -> new CollectionWrapper<>(new ArrayList<>()), + final var underTest = + new WrappedCollectionBasedResponseTransformer, Collection, String, Long>( + () -> new CollectionWrapper<>(new ArrayList<>()), CollectionWrapper::getCollection, (wrapper, collection) -> { wrapper.setCollection(collection); @@ -63,7 +65,7 @@ void testSplitToPartialResponseShouldSplitValidInput(final CollectionWrapper> actual = underTest.splitToPartialResponse(input); + final var actual = underTest.splitToPartialResponse(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -71,11 +73,13 @@ void testSplitToPartialResponseShouldSplitValidInput(final CollectionWrapper> input, - final CollectionWrapper expected) { + void testMergeToBatchResponseShouldMergeValidInput( + final Map> input, + final CollectionWrapper expected) { //given - final WrappedCollectionBasedResponseTransformer, Collection, String, Long> underTest = - new WrappedCollectionBasedResponseTransformer<>(w -> new CollectionWrapper<>(new ArrayList<>()), + final var underTest = + new WrappedCollectionBasedResponseTransformer, Collection, String, Long>( + w -> new CollectionWrapper<>(new ArrayList<>()), CollectionWrapper::getCollection, (wrapper, collection) -> { wrapper.setCollection(collection); @@ -83,7 +87,7 @@ void testMergeToBatchResponseShouldMergeValidInput(final Map actual = underTest.mergeToBatchResponse(input); + final var actual = underTest.mergeToBatchResponse(input); //then assertEquals(expected, actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformerTest.java index b33b909..733e84a 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedRequestTransformerTest.java @@ -48,17 +48,19 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialRequestShouldSplitValidInput(final MapWrapper input, - final Map> expected) { + void testSplitToPartialRequestShouldSplitValidInput( + final MapWrapper input, + final Map> expected) { //given - final WrappedMapBasedRequestTransformer, Map, String, Long> underTest = - new WrappedMapBasedRequestTransformer<>(() -> new MapWrapper<>(new HashMap<>()), MapWrapper::getMap, (wrapper, map) -> { + final var underTest = + new WrappedMapBasedRequestTransformer, Map, String, Long>( + () -> new MapWrapper<>(new HashMap<>()), MapWrapper::getMap, (wrapper, map) -> { wrapper.setMap(map); return wrapper; }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); //when - final Map> actual = underTest.splitToPartialRequest(input); + final var actual = underTest.splitToPartialRequest(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -66,17 +68,21 @@ void testSplitToPartialRequestShouldSplitValidInput(final MapWrapper> input, - final MapWrapper expected) { + void testMergeToBatchRequestShouldMergeValidInput( + final Map> input, + final MapWrapper expected) { //given - final WrappedMapBasedRequestTransformer, Map, String, Long> underTest = - new WrappedMapBasedRequestTransformer<>(w -> new MapWrapper<>(new HashMap<>()), MapWrapper::getMap, (wrapper, map) -> { - wrapper.setMap(map); - return wrapper; - }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + final var underTest = + new WrappedMapBasedRequestTransformer, Map, String, Long>( + w -> new MapWrapper<>(new HashMap<>()), + MapWrapper::getMap, + (wrapper, map) -> { + wrapper.setMap(map); + return wrapper; + }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); //when - final MapWrapper actual = underTest.mergeToBatchRequest(input); + final var actual = underTest.mergeToBatchRequest(input); //then assertEquals(expected, actual); diff --git a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformerTest.java b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformerTest.java index 20ce450..5e51fb0 100644 --- a/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformerTest.java +++ b/src/test/java/com/github/nagyesta/cacheonly/transform/common/WrappedMapBasedResponseTransformerTest.java @@ -48,17 +48,21 @@ private static Stream mergeInputProvider() { @ParameterizedTest @MethodSource("splitInputProvider") - void testSplitToPartialResponseShouldSplitValidInput(final MapWrapper input, - final Map> expected) { + void testSplitToPartialResponseShouldSplitValidInput( + final MapWrapper input, + final Map> expected) { //given - final WrappedMapBasedResponseTransformer, Map, String, Long> underTest = - new WrappedMapBasedResponseTransformer<>(() -> new MapWrapper<>(new HashMap<>()), MapWrapper::getMap, (wrapper, map) -> { - wrapper.setMap(map); - return wrapper; - }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + final var underTest = + new WrappedMapBasedResponseTransformer, Map, String, Long>( + () -> new MapWrapper<>(new HashMap<>()), + MapWrapper::getMap, + (wrapper, map) -> { + wrapper.setMap(map); + return wrapper; + }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); //when - final Map> actual = underTest.splitToPartialResponse(input); + final var actual = underTest.splitToPartialResponse(input); //then assertIterableEquals(expected.entrySet(), actual.entrySet()); @@ -66,17 +70,21 @@ void testSplitToPartialResponseShouldSplitValidInput(final MapWrapper> input, - final MapWrapper expected) { + void testMergeToBatchResponseShouldMergeValidInput( + final Map> input, + final MapWrapper expected) { //given - final WrappedMapBasedResponseTransformer, Map, String, Long> underTest = - new WrappedMapBasedResponseTransformer<>(w -> new MapWrapper<>(new HashMap<>()), MapWrapper::getMap, (wrapper, map) -> { - wrapper.setMap(map); - return wrapper; - }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + final var underTest = + new WrappedMapBasedResponseTransformer, Map, String, Long>( + w -> new MapWrapper<>(new HashMap<>()), + MapWrapper::getMap, + (wrapper, map) -> { + wrapper.setMap(map); + return wrapper; + }, Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); //when - final MapWrapper actual = underTest.mergeToBatchResponse(input); + final var actual = underTest.mergeToBatchResponse(input); //then assertEquals(expected, actual);