diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6e46960..439ab84 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,10 +12,10 @@ jobs: steps: # Checkout repo using https://github.com/marketplace/actions/checkout - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 17 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 994b5ea..15e3d25 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,14 +6,14 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Import GPG Key - uses: crazy-max/ghaction-import-gpg@v5 + uses: crazy-max/ghaction-import-gpg@v6 with: gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.GPG_PASSPHRASE }} - name: Set up Maven Central Repository - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: 17 diff --git a/README.adoc b/README.adoc index f7932d9..74bea0f 100644 --- a/README.adoc +++ b/README.adoc @@ -9,6 +9,11 @@ image:https://github.com/aerospike-community/spring-data-aerospike-starters/work |=== |`spring-data-aerospike-starters` |`spring-data-aerospike` |`aerospike-client` |`aerospike-reactor-client` +|0.13.x +|4.6.x +|7.2.x +|7.1.x + |0.12.x |4.5.x |7.1.x diff --git a/pom.xml b/pom.xml index 8cb00aa..0d2cd8a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-dependencies - 3.1.2 + 3.2.0 com.aerospike @@ -31,7 +31,7 @@ - 0.12.0 + 0.13.0 17 ${java.version} ${java.version} @@ -40,11 +40,11 @@ 1.6 1.5.0 - 4.5.0 - 7.0.0 - 7.1.0 + 4.6.0 + 7.1.0 + 7.2.0 - 4.0.4 + 4.1.0 diff --git a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/aerospike/AerospikeAutoConfiguration.java b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/aerospike/AerospikeAutoConfiguration.java index 23528e3..85f74f2 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/aerospike/AerospikeAutoConfiguration.java +++ b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/aerospike/AerospikeAutoConfiguration.java @@ -21,19 +21,17 @@ import com.aerospike.client.IAerospikeClient; import com.aerospike.client.async.EventLoops; import com.aerospike.client.async.NioEventLoops; -import com.aerospike.client.policy.BatchPolicy; -import com.aerospike.client.policy.ClientPolicy; -import com.aerospike.client.policy.Policy; -import com.aerospike.client.policy.QueryPolicy; -import com.aerospike.client.policy.WritePolicy; +import com.aerospike.client.policy.*; import com.aerospike.client.reactor.AerospikeReactorClient; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.data.aerospike.AerospikeDataProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.data.aerospike.server.version.ServerVersionSupport; import reactor.core.publisher.Flux; import java.util.Optional; @@ -58,6 +56,22 @@ public AerospikeClient aerospikeClient(AerospikeProperties properties, return new AerospikeClient(aerospikeClientPolicy, hosts); } + @Bean(name = "aerospikeServerVersionSupport") + @ConditionalOnMissingBean(ServerVersionSupport.class) + public ServerVersionSupport serverVersionSupport(IAerospikeClient aerospikeClient, + AerospikeDataProperties properties) { + ServerVersionSupport serverVersionSupport = new ServerVersionSupport(aerospikeClient); + processServerVersionRefreshFrequency(properties.getServerVersionRefreshSeconds(), serverVersionSupport); + return serverVersionSupport; + } + + private void processServerVersionRefreshFrequency(int serverVersionRefreshSeconds, + ServerVersionSupport serverVersionSupport) { + if (serverVersionRefreshSeconds > 0) { + serverVersionSupport.scheduleServerVersionRefresh(serverVersionRefreshSeconds); + } + } + @Bean(name = "aerospikeClientPolicy") @ConditionalOnMissingBean public ClientPolicy aerospikeClientPolicy(AerospikeProperties properties, diff --git a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeCommonDataConfiguration.java b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeCommonDataConfiguration.java index f01a711..dedd01a 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeCommonDataConfiguration.java +++ b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeCommonDataConfiguration.java @@ -1,11 +1,13 @@ package org.springframework.boot.autoconfigure.data.aerospike; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.domain.EntityScanner; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.data.aerospike.config.AerospikeDataSettings; import org.springframework.data.aerospike.convert.AerospikeCustomConversions; import org.springframework.data.aerospike.convert.AerospikeTypeAliasAccessor; import org.springframework.data.aerospike.convert.MappingAerospikeConverter; @@ -23,6 +25,7 @@ import java.util.Collections; +@Slf4j @AutoConfiguration class AerospikeCommonDataConfiguration { @@ -54,8 +57,10 @@ public IndexesCacheHolder aerospikeIndexCache() { @ConditionalOnMissingBean(name = "mappingAerospikeConverter") public MappingAerospikeConverter mappingAerospikeConverter(AerospikeMappingContext aerospikeMappingContext, AerospikeTypeAliasAccessor aerospikeTypeAliasAccessor, - AerospikeCustomConversions aerospikeCustomConversions) { - return new MappingAerospikeConverter(aerospikeMappingContext, aerospikeCustomConversions, aerospikeTypeAliasAccessor); + AerospikeCustomConversions aerospikeCustomConversions, + AerospikeDataProperties aerospikeDataProperties) { + return new MappingAerospikeConverter(aerospikeMappingContext, aerospikeCustomConversions, + aerospikeTypeAliasAccessor, aerospikeDataSettings(aerospikeDataProperties)); } @Bean(name = "aerospikeTypeAliasAccessor") @@ -75,7 +80,8 @@ public AerospikeCustomConversions aerospikeCustomConversions() { @ConditionalOnMissingBean(name = "aerospikeMappingContext") public AerospikeMappingContext aerospikeMappingContext(ApplicationContext applicationContext, AerospikeCustomConversions aerospikeCustomConversions, - AerospikeDataProperties aerospikeDataProperties) throws Exception { + AerospikeDataProperties aerospikeDataProperties) + throws Exception { AerospikeMappingContext context = new AerospikeMappingContext(); context.setInitialEntitySet(new EntityScanner(applicationContext).scan(Document.class, Persistent.class)); context.setSimpleTypeHolder(aerospikeCustomConversions.getSimpleTypeHolder()); @@ -91,4 +97,17 @@ public AerospikeMappingContext aerospikeMappingContext(ApplicationContext applic public AerospikeExceptionTranslator aerospikeExceptionTranslator() { return new DefaultAerospikeExceptionTranslator(); } + + private AerospikeDataSettings aerospikeDataSettings(AerospikeDataProperties aerospikeDataProperties) { + AerospikeDataSettings.AerospikeDataSettingsBuilder builder = AerospikeDataSettings.builder(); + configureDataSettings(builder, aerospikeDataProperties); + return builder.build(); + } + + private void configureDataSettings(AerospikeDataSettings.AerospikeDataSettingsBuilder builder, + AerospikeDataProperties aerospikeDataProperties) { + builder.scansEnabled(aerospikeDataProperties.isScansEnabled()); + builder.sendKey(aerospikeDataProperties.isSendKey()); + builder.createIndexesOnStartup(aerospikeDataProperties.isCreateIndexesOnStartup()); + } } diff --git a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataConfiguration.java b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataConfiguration.java index 8403459..3bcafbe 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataConfiguration.java +++ b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataConfiguration.java @@ -17,11 +17,13 @@ package org.springframework.boot.autoconfigure.data.aerospike; import com.aerospike.client.IAerospikeClient; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Lazy; +import org.springframework.data.aerospike.config.AerospikeDataSettings; import org.springframework.data.aerospike.convert.MappingAerospikeConverter; import org.springframework.data.aerospike.core.AerospikeExceptionTranslator; import org.springframework.data.aerospike.core.AerospikeTemplate; @@ -35,6 +37,7 @@ import org.springframework.data.aerospike.query.cache.IndexRefresher; import org.springframework.data.aerospike.query.cache.IndexesCacheUpdater; import org.springframework.data.aerospike.query.cache.InternalIndexOperations; +import org.springframework.data.aerospike.server.version.ServerVersionSupport; /** * Configure Spring Data's Aerospike support. @@ -42,6 +45,7 @@ * @author Igor Ermolenko * @author Anastasiia Smirnova */ +@Slf4j @AutoConfiguration class AerospikeDataConfiguration { @@ -52,12 +56,14 @@ public AerospikeTemplate aerospikeTemplate(IAerospikeClient aerospikeClient, MappingAerospikeConverter mappingAerospikeConverter, AerospikeMappingContext aerospikeMappingContext, AerospikeExceptionTranslator aerospikeExceptionTranslator, - QueryEngine queryEngine, IndexRefresher indexRefresher) { + QueryEngine queryEngine, IndexRefresher indexRefresher, + ServerVersionSupport serverVersionSupport) { return new AerospikeTemplate(aerospikeClient, aerospikeDataProperties.getNamespace(), mappingAerospikeConverter, aerospikeMappingContext, - aerospikeExceptionTranslator, queryEngine, indexRefresher); + aerospikeExceptionTranslator, queryEngine, indexRefresher, + serverVersionSupport); } @Bean(name = "aerospikeQueryEngine") @@ -66,26 +72,55 @@ public QueryEngine aerospikeQueryEngine(IAerospikeClient aerospikeClient, AerospikeDataProperties aerospikeDataProperties, FilterExpressionsBuilder filterExpressionsBuilder, StatementBuilder statementBuilder) { - QueryEngine queryEngine = new QueryEngine(aerospikeClient, statementBuilder, filterExpressionsBuilder, aerospikeClient.getQueryPolicyDefault()); + QueryEngine queryEngine = new QueryEngine(aerospikeClient, statementBuilder, filterExpressionsBuilder); queryEngine.setScansEnabled(aerospikeDataProperties.isScansEnabled()); + queryEngine.setQueryMaxRecords(aerospikeDataProperties.getQueryMaxRecords()); return queryEngine; } @Bean(name = "aerospikeIndexRefresher") @ConditionalOnMissingBean(name = "aerospikeIndexRefresher") - public IndexRefresher aerospikeIndexRefresher(IAerospikeClient aerospikeClient, IndexesCacheUpdater indexesCacheUpdater) { - IndexRefresher refresher = new IndexRefresher(aerospikeClient, aerospikeClient.getInfoPolicyDefault(), new InternalIndexOperations(new IndexInfoParser()), indexesCacheUpdater); + public IndexRefresher indexRefresher(IAerospikeClient aerospikeClient, IndexesCacheUpdater indexesCacheUpdater, + ServerVersionSupport serverVersionSupport, + AerospikeDataProperties aerospikeDataProperties) { + IndexRefresher refresher = new IndexRefresher(aerospikeClient, aerospikeClient.getInfoPolicyDefault(), + new InternalIndexOperations(new IndexInfoParser()), indexesCacheUpdater, serverVersionSupport); refresher.refreshIndexes(); + int refreshFrequency = aerospikeDataSettings(aerospikeDataProperties).getIndexCacheRefreshSeconds(); + processCacheRefreshFrequency(refreshFrequency, refresher); return refresher; } + private void processCacheRefreshFrequency(int indexCacheRefreshSeconds, IndexRefresher indexRefresher) { + if (indexCacheRefreshSeconds <= 0) { + log.info("Periodic index cache refreshing is not scheduled, interval ({}) is <= 0", + indexCacheRefreshSeconds); + } else { + indexRefresher.scheduleRefreshIndexes(indexCacheRefreshSeconds); + } + } + @Bean @ConditionalOnMissingBean(name = "aerospikePersistenceEntityIndexCreator") public AerospikePersistenceEntityIndexCreator aerospikePersistenceEntityIndexCreator( AerospikeDataProperties aerospikeDataProperties, - @Lazy AerospikeTemplate template, + @Lazy ObjectProvider template, ObjectProvider aerospikeMappingContext, AerospikeIndexResolver aerospikeIndexResolver) { - return new AerospikePersistenceEntityIndexCreator(aerospikeMappingContext, aerospikeDataProperties.isCreateIndexesOnStartup(), aerospikeIndexResolver, template); + return new AerospikePersistenceEntityIndexCreator(aerospikeMappingContext, + aerospikeDataProperties.isCreateIndexesOnStartup(), aerospikeIndexResolver, template); + } + + private AerospikeDataSettings aerospikeDataSettings(AerospikeDataProperties aerospikeDataProperties) { + AerospikeDataSettings.AerospikeDataSettingsBuilder builder = AerospikeDataSettings.builder(); + configureDataSettings(builder, aerospikeDataProperties); + return builder.build(); + } + + private void configureDataSettings(AerospikeDataSettings.AerospikeDataSettingsBuilder builder, + AerospikeDataProperties aerospikeDataProperties) { + builder.scansEnabled(aerospikeDataProperties.isScansEnabled()); + builder.sendKey(aerospikeDataProperties.isSendKey()); + builder.createIndexesOnStartup(aerospikeDataProperties.isCreateIndexesOnStartup()); } } diff --git a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataProperties.java b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataProperties.java index 1f62881..6580c8f 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataProperties.java +++ b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataProperties.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.data.aerospike; +import lombok.Getter; +import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -25,6 +27,8 @@ * @author Anastasiia Smirnova */ @ConfigurationProperties(prefix = "spring.data.aerospike") +@Getter +@Setter public class AerospikeDataProperties { /** @@ -55,43 +59,34 @@ public class AerospikeDataProperties { */ private boolean createIndexesOnStartup = true; - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getTypeKey() { - return typeKey; - } - - public void setTypeKey(String typeKey) { - this.typeKey = typeKey; - } - - public boolean isScansEnabled() { - return scansEnabled; - } + /** + * Send user defined key in addition to hash digest on both reads and writes + */ + private boolean sendKey = true; - public void setScansEnabled(boolean scansEnabled) { - this.scansEnabled = scansEnabled; - } + /** + * Automatically refresh indexes cache every seconds + */ + private int indexCacheRefreshSeconds = 3600; - public Class getFieldNamingStrategy() { - return fieldNamingStrategy; - } + /** + * Automatically refresh cached server version every seconds + */ + private int serverVersionRefreshSeconds = 0; - public void setFieldNamingStrategy(Class fieldNamingStrategy) { - this.fieldNamingStrategy = fieldNamingStrategy; - } + /** + * Limit amount of results returned by server. Non-positive value means no limit. + */ + private long queryMaxRecords = 10_000L; - public boolean isCreateIndexesOnStartup() { - return createIndexesOnStartup; - } + /** + * Maximum batch size for batch write operations + */ + private int batchWriteSize = 100; - public void setCreateIndexesOnStartup(boolean createIndexesOnStartup) { - this.createIndexesOnStartup = createIndexesOnStartup; - } + /** + * Define how @Id fields (primary keys) and Map keys are stored: false - always as String, + * true - preserve original type if supported + */ + private boolean keepOriginalKeyTypes = false; } diff --git a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataConfiguration.java b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataConfiguration.java index 33c0680..470b666 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataConfiguration.java +++ b/spring-boot-autoconfigure-data-aerospike/src/main/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataConfiguration.java @@ -35,6 +35,7 @@ import org.springframework.data.aerospike.query.cache.IndexesCacheUpdater; import org.springframework.data.aerospike.query.cache.InternalIndexOperations; import org.springframework.data.aerospike.query.cache.ReactorIndexRefresher; +import org.springframework.data.aerospike.server.version.ServerVersionSupport; /** * Configure Spring Data's Reactive Aerospike support. @@ -52,9 +53,12 @@ public ReactiveAerospikeTemplate reactiveAerospikeTemplate(MappingAerospikeConve AerospikeMappingContext aerospikeMappingContext, AerospikeExceptionTranslator aerospikeExceptionTranslator, AerospikeReactorClient aerospikeReactorClient, - ReactorQueryEngine reactorQueryEngine, ReactorIndexRefresher reactorIndexRefresher) { - return new ReactiveAerospikeTemplate(aerospikeReactorClient, aerospikeDataProperties.getNamespace(), mappingAerospikeConverter, aerospikeMappingContext, - aerospikeExceptionTranslator, reactorQueryEngine, reactorIndexRefresher); + ReactorQueryEngine reactorQueryEngine, + ReactorIndexRefresher reactorIndexRefresher, + ServerVersionSupport serverVersionSupport) { + return new ReactiveAerospikeTemplate(aerospikeReactorClient, aerospikeDataProperties.getNamespace(), + mappingAerospikeConverter, aerospikeMappingContext, + aerospikeExceptionTranslator, reactorQueryEngine, reactorIndexRefresher, serverVersionSupport); } @Bean(name = "reactiveAerospikeQueryEngine") @@ -63,17 +67,20 @@ public ReactorQueryEngine reactiveAerospikeQueryEngine(AerospikeReactorClient ae AerospikeDataProperties aerospikeDataProperties, FilterExpressionsBuilder filterExpressionsBuilder, StatementBuilder statementBuilder) { - ReactorQueryEngine queryEngine = new ReactorQueryEngine(aerospikeReactorClient, statementBuilder, filterExpressionsBuilder, aerospikeReactorClient.getQueryPolicyDefault()); + ReactorQueryEngine queryEngine = new ReactorQueryEngine(aerospikeReactorClient, statementBuilder, + filterExpressionsBuilder); queryEngine.setScansEnabled(aerospikeDataProperties.isScansEnabled()); + queryEngine.setQueryMaxRecords(aerospikeDataProperties.getQueryMaxRecords()); return queryEngine; } @Bean(name = "reactiveAerospikeIndexRefresher") @ConditionalOnMissingBean(name = "reactiveAerospikeIndexRefresher") public ReactorIndexRefresher reactiveAerospikeIndexRefresher(AerospikeReactorClient aerospikeReactorClient, - IndexesCacheUpdater indexesCacheUpdater) { + IndexesCacheUpdater indexesCacheUpdater, + ServerVersionSupport serverVersionSupport) { ReactorIndexRefresher refresher = new ReactorIndexRefresher(aerospikeReactorClient, aerospikeReactorClient.getInfoPolicyDefault(), - new InternalIndexOperations(new IndexInfoParser()), indexesCacheUpdater); + new InternalIndexOperations(new IndexInfoParser()), indexesCacheUpdater, serverVersionSupport); refresher.refreshIndexes().block(); return refresher; } @@ -82,10 +89,11 @@ public ReactorIndexRefresher reactiveAerospikeIndexRefresher(AerospikeReactorCli @ConditionalOnMissingBean(name = "reactiveAerospikePersistenceEntityIndexCreator") public ReactiveAerospikePersistenceEntityIndexCreator reactiveAerospikePersistenceEntityIndexCreator( AerospikeDataProperties aerospikeDataProperties, - @Lazy ReactiveAerospikeTemplate template, + @Lazy ObjectProvider template, ObjectProvider aerospikeMappingContext, AerospikeIndexResolver aerospikeIndexResolver) { - return new ReactiveAerospikePersistenceEntityIndexCreator(aerospikeMappingContext, aerospikeDataProperties.isCreateIndexesOnStartup(), + return new ReactiveAerospikePersistenceEntityIndexCreator(aerospikeMappingContext, + aerospikeDataProperties.isCreateIndexesOnStartup(), aerospikeIndexResolver, template); } diff --git a/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataAutoConfigurationTest.java b/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataAutoConfigurationTest.java index 15f1d67..abf9d50 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataAutoConfigurationTest.java +++ b/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeDataAutoConfigurationTest.java @@ -22,6 +22,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.aerospike.AerospikeAutoConfiguration; import org.springframework.boot.autoconfigure.aerospike.AerospikeProperties; +import org.springframework.boot.autoconfigure.data.aerospike.AerospikeTestConfigurations.AerospikeServerVersionSupportMockConfiguration; import org.springframework.boot.autoconfigure.data.aerospike.AerospikeTestConfigurations.EntityScanConfiguration; import org.springframework.boot.autoconfigure.data.aerospike.city.City; import org.springframework.boot.test.context.FilteredClassLoader; @@ -32,9 +33,6 @@ import org.springframework.data.aerospike.core.ReactiveAerospikeTemplate; import org.springframework.data.aerospike.mapping.AerospikeMappingContext; import org.springframework.data.util.TypeInformation; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.autoconfigure.data.aerospike.AerospikeTestConfigurations.AerospikeClientMockConfiguration; @@ -49,7 +47,7 @@ */ public class AerospikeDataAutoConfigurationTest { - private ApplicationContextRunner contextRunner = new ApplicationContextRunner() + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withClassLoader(new FilteredClassLoader(AerospikeReactorClient.class)) .withConfiguration(AutoConfigurations.of( AerospikeAutoConfiguration.class, AerospikeDataAutoConfiguration.class)); @@ -65,12 +63,12 @@ public void aerospikeTemplateAndClientAreNotSetupWhenNeitherClientNorDataPropert } @Test - @SuppressWarnings("unchecked") public void entityScanShouldSetInitialEntitySet() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(EntityScanConfiguration.class, AerospikeClientMockConfiguration.class) + .withUserConfiguration(EntityScanConfiguration.class, AerospikeClientMockConfiguration.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { AerospikeMappingContext mappingContext = context.getBean(AerospikeMappingContext.class); assertThat(mappingContext.getManagedTypes()).containsOnly(TypeInformation.of(City.class)); @@ -82,7 +80,8 @@ public void typeKeyDefault() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { AerospikeTypeAliasAccessor aliasAccessor = context.getBean(AerospikeTypeAliasAccessor.class); String typeKey = getField(aliasAccessor, "typeKey"); @@ -97,7 +96,8 @@ public void typeKeyCanBeCustomized() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, + AerospikeServerVersionSupportMockConfiguration.class) .withPropertyValues("spring.data.aerospike.type-key=++amazing++") .run((context) -> { AerospikeTypeAliasAccessor aliasAccessor = context.getBean(AerospikeTypeAliasAccessor.class); @@ -112,7 +112,8 @@ public void typeKeyCanBeNull() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, + AerospikeServerVersionSupportMockConfiguration.class) .withPropertyValues("spring.data.aerospike.type-key=") .run((context) -> { AerospikeTypeAliasAccessor aliasAccessor = context.getBean(AerospikeTypeAliasAccessor.class); @@ -127,7 +128,8 @@ public void customConversions() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(CustomConversionsConfig.class, AerospikeClientMockConfiguration.class) + .withUserConfiguration(CustomConversionsConfig.class, AerospikeClientMockConfiguration.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { MappingAerospikeConverter converter = context.getBean(MappingAerospikeConverter.class); assertThat(converter.getConversionService().canConvert(City.class, String.class)).isTrue(); @@ -139,7 +141,8 @@ public void configurationIsApplied() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { assertThat(context).doesNotHaveBean(ReactiveAerospikeTemplate.class); assertThat(context).hasSingleBean(AerospikeTemplate.class); @@ -148,5 +151,4 @@ public void configurationIsApplied() { assertThat(context).hasSingleBean(AerospikeMappingContext.class); }); } - } diff --git a/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataAutoConfigurationTest.java b/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataAutoConfigurationTest.java index 339f6ac..0be59b4 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataAutoConfigurationTest.java +++ b/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeReactiveDataAutoConfigurationTest.java @@ -22,6 +22,7 @@ import org.springframework.boot.autoconfigure.aerospike.AerospikeAutoConfiguration; import org.springframework.boot.autoconfigure.aerospike.AerospikeProperties; import org.springframework.boot.autoconfigure.data.aerospike.AerospikeTestConfigurations.AerospikeClientMockConfiguration; +import org.springframework.boot.autoconfigure.data.aerospike.AerospikeTestConfigurations.AerospikeServerVersionSupportMockConfiguration; import org.springframework.boot.autoconfigure.data.aerospike.AerospikeTestConfigurations.MockReactiveIndexRefresher; import org.springframework.boot.autoconfigure.data.aerospike.city.City; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -43,7 +44,7 @@ */ public class AerospikeReactiveDataAutoConfigurationTest { - private ApplicationContextRunner contextRunner = new ApplicationContextRunner() + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of( AerospikeAutoConfiguration.class, AerospikeReactiveDataAutoConfiguration.class)); @@ -59,12 +60,13 @@ public void aerospikeTemplateAndClientAreNotSetupWhenNeitherClientNorDataPropert } @Test - @SuppressWarnings("unchecked") public void entityScanShouldSetInitialEntitySet() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeTestConfigurations.EntityScanConfiguration.class, AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class) + .withUserConfiguration(AerospikeTestConfigurations.EntityScanConfiguration.class, + AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { AerospikeMappingContext mappingContext = context.getBean(AerospikeMappingContext.class); assertThat(mappingContext.getManagedTypes()).containsOnly(TypeInformation.of(City.class)); @@ -76,7 +78,8 @@ public void typeKeyDefault() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { AerospikeTypeAliasAccessor aliasAccessor = context.getBean(AerospikeTypeAliasAccessor.class); String typeKey = getField(aliasAccessor, "typeKey"); @@ -91,7 +94,8 @@ public void typeKeyCanBeCustomized() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class, + AerospikeServerVersionSupportMockConfiguration.class) .withPropertyValues("spring.data.aerospike.type-key=++amazing++") .run((context) -> { AerospikeTypeAliasAccessor aliasAccessor = context.getBean(AerospikeTypeAliasAccessor.class); @@ -106,7 +110,9 @@ public void customConversions() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeTestConfigurations.CustomConversionsConfig.class, AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class) + .withUserConfiguration(AerospikeTestConfigurations.CustomConversionsConfig.class, + AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { MappingAerospikeConverter converter = context.getBean(MappingAerospikeConverter.class); assertThat(converter.getConversionService().canConvert(City.class, String.class)).isTrue(); @@ -118,7 +124,8 @@ public void configurationIsApplied() { contextRunner .withPropertyValues("spring.aerospike.hosts=localhost:3000") .withPropertyValues("spring.data.aerospike.namespace=TEST") - .withUserConfiguration(AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class) + .withUserConfiguration(AerospikeClientMockConfiguration.class, MockReactiveIndexRefresher.class, + AerospikeServerVersionSupportMockConfiguration.class) .run(context -> { assertThat(context).doesNotHaveBean(AerospikeTemplate.class); assertThat(context).hasSingleBean(ReactiveAerospikeTemplate.class); @@ -127,5 +134,4 @@ public void configurationIsApplied() { assertThat(context).hasSingleBean(AerospikeMappingContext.class); }); } - } diff --git a/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeTestConfigurations.java b/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeTestConfigurations.java index c64326d..f771852 100644 --- a/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeTestConfigurations.java +++ b/spring-boot-autoconfigure-data-aerospike/src/test/java/org/springframework/boot/autoconfigure/data/aerospike/AerospikeTestConfigurations.java @@ -2,21 +2,18 @@ import com.aerospike.client.IAerospikeClient; import com.aerospike.client.cluster.Node; -import com.aerospike.client.policy.InfoPolicy; import com.aerospike.client.policy.WritePolicy; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.data.aerospike.city.City; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.data.aerospike.convert.AerospikeCustomConversions; import org.springframework.data.aerospike.query.cache.ReactorIndexRefresher; -import reactor.core.publisher.Mono; +import org.springframework.data.aerospike.server.version.ServerVersionSupport; -import java.util.Arrays; +import java.util.List; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -32,7 +29,17 @@ public IAerospikeClient aerospikeClientMock() { when(client.getWritePolicyDefault()).thenReturn(new WritePolicy()); return client; } + } + + @AutoConfiguration + public static class AerospikeServerVersionSupportMockConfiguration { + @Bean + public ServerVersionSupport aerospikeServerVersionSupportMock() { + ServerVersionSupport serverVersionSupport = mock(ServerVersionSupport.class); + when(serverVersionSupport.getServerVersion()).thenReturn("5.0.0.0"); + return serverVersionSupport; + } } @AutoConfiguration @@ -55,9 +62,8 @@ public static class CustomConversionsConfig { @Bean(name = "aerospikeCustomConversions") AerospikeCustomConversions myCustomConversions() { - return new AerospikeCustomConversions(Arrays.asList(new CityToStringConverter())); + return new AerospikeCustomConversions(List.of(new CityToStringConverter())); } - } public static class CityToStringConverter implements Converter { @@ -66,6 +72,5 @@ public static class CityToStringConverter implements Converter { public String convert(City value) { return value.getName(); } - } } diff --git a/spring-boot-starter-data-aerospike-example/pom.xml b/spring-boot-starter-data-aerospike-example/pom.xml index 842d16d..24dd73e 100644 --- a/spring-boot-starter-data-aerospike-example/pom.xml +++ b/spring-boot-starter-data-aerospike-example/pom.xml @@ -16,7 +16,7 @@ Example for using Spring Boot Data Aerospike Starter - 2.3.2 + 3.1.1 diff --git a/spring-boot-starter-data-aerospike-example/reactive/src/test/java/com/aerospike/example/reactive/ReactiveIntegrationTest.java b/spring-boot-starter-data-aerospike-example/reactive/src/test/java/com/aerospike/example/reactive/ReactiveIntegrationTest.java index f1101eb..75bf769 100644 --- a/spring-boot-starter-data-aerospike-example/reactive/src/test/java/com/aerospike/example/reactive/ReactiveIntegrationTest.java +++ b/spring-boot-starter-data-aerospike-example/reactive/src/test/java/com/aerospike/example/reactive/ReactiveIntegrationTest.java @@ -2,12 +2,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.*; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; @@ -90,5 +85,4 @@ void savesAndFindsByLastName() { .body("[0].age", equalTo(61)) ; } - }